diff options
author | Karl Berry <karl@freefriends.org> | 2012-05-07 22:50:52 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2012-05-07 22:50:52 +0000 |
commit | d543752477df00db9845d783c27fd913a48c6f73 (patch) | |
tree | f1d8f6958eba4bf4d22dda07a9fbc85298b4d7be /Master/texmf-dist/source | |
parent | d62dfb02a03e1cd263bfbd6f33fda7006178193d (diff) |
xecjk (7may12)
git-svn-id: svn://tug.org/texlive/trunk@26246 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r-- | Master/texmf-dist/source/xelatex/xecjk/xeCJK.dtx | 5554 | ||||
-rw-r--r-- | Master/texmf-dist/source/xelatex/xecjk/xeCJK.ins | 63 |
2 files changed, 3686 insertions, 1931 deletions
diff --git a/Master/texmf-dist/source/xelatex/xecjk/xeCJK.dtx b/Master/texmf-dist/source/xelatex/xecjk/xeCJK.dtx index 13c8f2a3f8e..02c37f43c4b 100644 --- a/Master/texmf-dist/source/xelatex/xecjk/xeCJK.dtx +++ b/Master/texmf-dist/source/xelatex/xecjk/xeCJK.dtx @@ -1,4 +1,4 @@ -% \iffalse +% \iffalse meta-comment %<*internal> \iffalse %</internal> @@ -21,7 +21,9 @@ may observe http://code.google.com/p/ctex-kit/updates/list -- Sun Wenchang <sunwch@hotmail.com> +- Sun Wenchang <sunwch@hotmail.com> +- Leo Liu <leoliu.pku@gmail.com> +- Qing Lee <sobenlee@gmail.com> %</readme> %<*internal> @@ -36,2136 +38,3879 @@ may observe \keepsilent \preamble - Version 2.4.5 (31-Jan-2012) - - Copyright (C) Wenchang Sun <sunwch@hotmail.com> - - This file may be distributed and/or modified under the - conditions of the LaTeX Project Public License, either version 1.3 - 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.3 or later is part of all distributions of LaTeX - version 2005/12/01 or later. + Version 3.0.4 (06-May-2012) +----------------------------------------------------------------- + Author: Wenchang Sun <sunwch@hotmail.com> + Maintainer: Leo Liu <leoliu.pku@gmail.com> + Qing Lee <sobenlee@gmail.com> + Copyright (C) 2007--2012 Wenchang Sun + + This file may be distributed and/or modified under the + conditions of the LaTeX Project Public License, either version 1.3 + 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.3 or later is part of all distributions of LaTeX + version 2005/12/01 or later. + + This work has the LPPL maintenance status "maintained". + The Current Maintainer of this work are Leo Liu and Qing Lee. +----------------------------------------------------------------- \endpreamble +\postamble +\endpostamble \askforoverwritefalse -\generate{\file{xeCJK.sty}{\from{xeCJK.dtx}{xeCJK}}} -\generate{\file{example-addspaces.tex}{\from{xeCJK.dtx}{example-addspaces}}} -\generate{\file{example-CJKchecksingle.tex}{\from{xeCJK.dtx}{example-CJKchecksingle}}} -\generate{\file{example-CJKfntef.tex}{\from{xeCJK.dtx}{example-CJKfntef}}} -\generate{\file{example-fallback.tex}{\from{xeCJK.dtx}{example-fallback}}} +\generate{\file{\jobname.sty}{\from{\jobname.dtx}{package}}} +\generate{\file{example-autofake.tex}{\from{\jobname.dtx}{ex-autofake}}} +\generate{\file{example-fallback.tex}{\from{\jobname.dtx}{ex-fallback}}} +\generate{\file{example-subCJKblock.tex}{\from{\jobname.dtx}{ex-block}}} %</batchfile> %<batchfile>\endbatchfile %<*internal> -\generate{\file{xeCJK.ins}{\from{xeCJK.dtx}{batchfile}}} +\generate{\file{\jobname.ins}{\from{\jobname.dtx}{batchfile}}} \nopreamble\nopostamble \generate{\file{README.txt}{\from{\jobname.dtx}{readme}}} \endgroup %</internal> % %<*driver> -\documentclass[12pt]{ltxdoc} -\usepackage{xcolor} -\usepackage[bookmarks=true,bookmarksopen=true,pdfstartview=FitH]{hyperref} -\usepackage[BoldFont,SlantFont,CJKnumber]{xeCJK} -\textheight 210mm -\textwidth 150mm -\oddsidemargin 0pt -\evensidemargin 0pt -\defaultfontfeatures{Ligatures=TeX} -\ifcsname CJKmainfont\endcsname -\else - \def\CJKmainfont{AR PLBaosong2GBK Light} -\fi -\setCJKmainfont{\CJKmainfont}% 设置缺省中文字体 -\setCJKmonofont*{\CJKmainfont}% 设置 中文字体 -\setCJKfamilyfont{song}{\CJKmainfont}% 设置 中文字体 -\def\xeCJK{{\textcolor{blue}{\texttt{xeCJK}}}} -% macros -{\catcode`\|=0 \catcode`\\=12 - |gdef|bslash{\}} - -\newcommand{\defmacro}[1]{% % Define a macro. - \textcolor{macrocolor}{\string#1}\index{\string\verb+\string#1+}% -} - -\newcommand{\usemacro}[1]{% % Define a macro. - \textcolor{macrocolor}{\string#1}% - #1\index{\string\verb+\string#1+}% -} - -\definecolor{parametercolor}{rgb}{1,0,1} -\definecolor{optioncolor}{rgb}{0,0,1} -\definecolor{macrocolor}{rgb}{0,0,0.63} - -\newcommand{\usepmacro}[3][]{% - \edef\tempa{#1}% - \textcolor{macrocolor}{\string#2}% - \string{\textcolor{parametercolor}{#3}\string}% - \ifx\tempa\@empty\else (#1)\fi% - #2{#3}\index{\string\verb+\string#2+}% -} - -\newenvironment{decl}[1][]% - {\par\small\addvspace{4.5ex plus 1ex}% - \vskip -\parskip - \ifx\relax#1\relax - \def\@decl@date{}% - \else - \def\@decl@date{\NEWfeature{#1}}% - \fi - \noindent\hspace{-\leftmargini}% - \begin{tabular}{|l|}\hline\ignorespaces}% - {\\\hline\end{tabular}\nobreak\@decl@date\par\nobreak - \vspace{2.3ex}\vskip -\parskip} - -\renewcommand{\arg}[1]{{\ttfamily\string{}\meta{#1}{\ttfamily\string}}} -\renewcommand{\meta}[1]{\mbox{\color{parametercolor}$\langle$\itshape #1\/$\rangle$}} - -\EnableCrossrefs -\CodelineIndex -\RecordChanges +\ProvidesFile{xeCJK.dtx} +%</driver> +% +%<*driver> +\documentclass{l3doc} +\hypersetup{pdfstartview=FitH} +\usepackage{xeCJK} +\usepackage{metalogo} +\setlist{nosep} +\setmainfont[Ligatures=TeX]{TeX Gyre Pagella} +\setmonofont{Inconsolata} +\setCJKmainfont[BoldFont=Adobe Heiti Std,ItalicFont=Adobe Kaiti Std]{Adobe Song Std} +\setCJKmonofont{Adobe Kaiti Std} +\xeCJKDeclareSubCJKBlock{HKMD} { "FF65 } +\xeCJKDeclareSubCJKBlock{Ext-B} { "20000 -> "2A6DF } +\xeCJKDeclareSubCJKBlock{Hangul}{ "1100 -> "11FF, "3130 -> "318F, "A960 -> "A97F, "AC00 -> "D7AF } +\setCJKmainfont[HKMD]{Microsoft YaHei} +\setCJKmainfont[Ext-B]{SimSun-ExtB} +\setCJKmainfont[Hangul]{Adobe Myungjo Std} +\xeCJKsetup{PunctStyle=kaiming,KaiMingPunct+={:;}} +\def\MacroFont{\small\normalfont\ttfamily\punctstyle{plain}} +\parindent=2em +\AtBeginDocument{\DeleteShortVerb{\"}\MakeShortVerb{\|}} +\addtolength{\voffset}{-5\baselineskip} +\addtolength\textheight{8\baselineskip} +\makeatletter +\let\orig@meta\meta +\def\meta#1{\orig@meta{\mbox{\normalfont\itshape\punctstyle{plain}\CJKsetecglue{}#1}}} +\def\TF{true\orvar{}false} +\def\TTF{\defaultvar{true}\orvar{}false} +\def\TFF{true\orvar\defaultvar{false}} +\def\orvar{\char`\|} +\let\defaultvar\textbf +\def\argbrace#1{\char`\{#1\char`\}} +\@addtoreset{CodelineNo}{section} +\makeatother \begin{document} -\ifxetex - \DocInput{xeCJK.dtx} - \makeatletter - \c@IndexColumns = 2 - \PrintIndex -\else - \makeatletter - \@latex@error{Use XeLaTeX to compile this file.} -\fi + \DocInput{\jobname.dtx} \end{document} %</driver> -% -%<*xeCJK> -\def\fileversion{2.4.5} -\def\filedate{2012/01/31} -\ProvidesPackage{xeCJK}[\filedate\space\fileversion\space package for typesetting CJK scripts with XeLaTeX] -%</xeCJK> -% % \fi % -% \makeatletter ^^A% To document @-cmds -% \errorcontextlines=999 ^^A% Show up all my mistakes -% -% \GetFileInfo{xeCJK.sty} +% \GetFileInfo{\jobname.sty} % -% \title{\hypertarget{Chinese}{xeCJK 宏包} -% \hbox to 0pt{\hskip 40mm\hyperlink{English}{\normalsize\texttt{English Version}}} -% \\[1ex] -% \normalsize 版本:\fileversion} -% \author{孙文昌} -% \date{\filedate} +% \title{\bfseries\pkg{xeCJK} 宏包} +% \author{\texttt{ctex.org}\thanks{\url{http://www.ctex.org}}} +% \date{\filedate\qquad\fileversion} % \maketitle % -% \newpage +% \begin{documentation} % % \section{简介} -% \parindent 2em -% \parskip 5pt % -% \xeCJK\ 是一个 XeLaTeX 宏包,用于排版 CJK 文字,包括字体选择和标点控制等。主要特点: +% \pkg{xeCJK} 是一个 \XeLaTeX 宏包,用于排版 CJK 文字,包括字体选择和标点控制 +% 等。主要特点: % \begin{enumerate} -% \item 分别设置CJK和英文字体; -% \item 自动忽略CJK文字间的空格而保留其它空格,允许在非标点汉字和英文字母 (a-z, A-Z) 间断行; -% \item 提供多种标点处理方式: 全角式、半角式、开明式、行末半角式; +% \item 分别设置 CJK 和英文字体; +% \item 自动忽略 CJK 文字间的空格而保留其它空格,允许在非标点汉字和英文 +% 字母 (a--z, A--Z) 间断行; +% \item 提供多种标点处理方式: 全角式、半角式、开明式、行末半角式和 CCT 式; % \item 自动调整中英文间空白。 % \end{enumerate} % -% \long\def\sometextsa{\xeCJK\ 是在CCT和CJK包基础上发展起来的, -% 支持多种标点格式。例如,“标点挤压”。\xeCJK\ 是在CCT和CJK包基础上 -% 发展起来的,支持多种标点格式。例如,“标点挤压”。} -% -% -% \usepmacro[全角式]{\punctstyle}{quanjiao} -% -% \sometextsa -% -% \usepmacro[半角式]{\punctstyle}{banjiao} -% -% \sometextsa -% -% -% \usepmacro[开明式]{\punctstyle}{kaiming} -% -% \sometextsa -% -% \usepmacro[行末半角式]{\punctstyle}{hangmobanjiao} -% -% \sometextsa -% -% {\usepmacro[plain]{\punctstyle}{plain} -% -% \sometextsa} -% -% \punctstyle{kaiming} +% \pkg{xeCJK} 的原始作者是孙文昌,目前由 +% \texttt{ctex-kit} \footnote{\url{http://code.google.com/p/ctex-kit/}}项目组 +% 维护,主要维护者是刘海洋\footnote{\nolinkurl{leoliu.pku@gmail.com}} 和 +% 李清\footnote{\nolinkurl{sobenlee@gmail.com}}。 % % \section{使用方法} % -% \xeCJK\ 使用了 XeTeX 的一些最新特性, 需要 XeTeX 0.9995.0 [2009/06/29] 以后的版本。 -% -% -% -% \begin{decl} -% \defmacro{\usepackage}[\textcolor{optioncolor}{Options}] -% \{\textcolor{parametercolor}{xeCJK}\} -% \end{decl} -% -% \begin{tabular}{ll} -% 宏包选项 & \\ -% BoldFont:& 启用CJK\textbf{粗体字}\\ -% SlantFont:& 启用 \textsl{斜体字slshape}\\ -% fallback: & 启用备用字体功能 \\ -% CJKnumber: & 调用CJKnumb宏包\\ -% CJKchecksingle: &避免单个汉字单独占一行\\ -% nospace: & 忽略 CJK 文字之间的空格(默认行为)\\ -% space: & 保留 CJK 文字之间的空格\\ -% \end{tabular} -% -% -% \begin{decl} -% \defmacro{\setCJKmainfont} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKsansfont} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKmonofont} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKmonofont*} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKmonofont+} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKfamilyfont} \arg{family name}[\textcolor{optioncolor} -% {<font features>}]\arg{font name}\\ -% \defmacro{\setCJKfallbackfamilyfont} \arg{family name} -% [\textcolor{optioncolor}{<font features>}]\arg{font name} -% \end{decl} -% 分别设置缺省 CJK 普通字体族、CJK 无衬线字体族、CJK 打字机字体族的各自所对应 -% 中文字体,以及某个 CJK 族所对应的备用字体(通常用于生僻字)。其中最后两个参 -% 数的意义请参考 \verb+fontspec+ 宏包。 -% -% 定义CJK字体时指定的\texttt{ItalicFont=\{...\}}比宏包的 -% \texttt{SlantFont}选项有更高的优先级。 -% 类似地,可以指定\texttt{BoldFont=\{font name\}}以抑制 -% \texttt{BoldFont}选项。 -% -% 可以重定义 \defmacro{\CJKfamilydefault} 来修改普通字体的 CJK 字体族。其默认 -% 值是默认的普通字体族 \defmacro{\CJKrmdefault},即 \verb+rm+。可以重定义为无 -% 衬线字体族的默认值 \defmacro{\CJKsfdefault},即 \verb+sf+;或是打字机字体族 -% 的 \defmacro{\CJKttdefault},即 \verb+tt+。也可以改为其他自定义的字体族。例 -% 如,在幻灯片中可以使用如下命令改用无衬线的汉字字体: -% \begin{verbatim} -% \renewcommand\CJKfamilydefault{\CJKsfdefault} -% \end{verbatim} -% -% \defmacro{\setCJKmonofont} 命令后面可以加上星号 |*| 或加号 |+|,分别表示使用 -% 放缩的方式或改变间距的方式,让 CJK 字符的宽度等于西文字体中两个空格的宽度。 -% 这有利于等宽字体的代码对齐等情形。 -% -% \defmacro{\CJKfixedspacing} 命令设置固定字距和不压缩标点格式,符合上面加 |+| -% 命令的意义。\defmacro{\CJKflexiblespacing} 命令恢复可伸缩的字距和标点压缩。 -% 抄录(|verbatim|)环境将自动使用 |\CJKfixedspacing| 的效果。 -% -% \defmacro{\setCJKmonoscale} 和 \defmacro{\setCJKmonoexspace} 命令分别计算并设置 -% 当前字号下西文等宽字体与 CJK 字体的放缩比例和字距,以符合上面加 |*| 与加 |+| 号 -% 命令的意义。在字号改变时,应该使用两个命令之一;但注意两个命令不能同时使用。 -% -% 与 CJK 包类似, 使用命令 \defmacro{\CJKfamily}\arg{family name} 改变当前中文字体。 -% -% -% \subsection*{例子} -% -% 以下命令设置缺省英文字体为 TeX Gyre Termes, 缺省中文字体为 AR PLBaosong2GBK Light (文鼎PL报宋二\kern 0sp GBK), -% 最后一个命令设置 CJKfamily “song”。 -% \begin{verbatim} -% \setmainfont{TeX Gyre Termes} -% \setCJKmainfont{AR PLBaosong2GBK Light} -% \setCJKfamilyfont{song}{AR PLBaosong2GBK Light} -% \end{verbatim} -% -% \noindent -% 下表中, 左边为输入, 右边为排版效果: -% -% \begin{tabular}{ll} -% \verb+这是缺省字体 abCD+ &这是缺省字体 abCD\\ -% \verb+\bfseries 这是缺省字体 abCD+ &{\bfseries 这是缺省字体 abCD}\\ -% \verb+\itshape 这是缺省字体 abCD+ &{\itshape 这是缺省字体 abCD}\\ -% \verb+\bfseries\itshape 这是缺省字体 abCD+ &\bfseries\itshape 这是缺省字体 abCD\\ -% \\ -% \verb+\CJKfamily{song}这是宋体+ &{\CJKfamily{song}这是宋体}\\ -% \end{tabular} -% -% -% -% -% -% \section{高级设置} -% -% \begin{decl} -% \defmacro{\punctstyle}\arg{punct style} -% \end{decl} +% \pkg{xeCJK} 使用了 \XeTeX 的一些最新特性,需要 \XeTeX{} |0.9995.0 [2009/06/29]| 以 +% 后的版本。\pkg{xeCJK} 还依赖 \pkg{fontspec}% +% \footnote{\url{http://mirrors.ctan.org/macros/latex/contrib/fontspec}}宏包来调用系统字体。 +% +% \pkg{xeCJK} 提供了将在 \ref{sec:xeCJK-opt} 节介绍的一些 \meta{key}|=|\meta{var} 形式的 +% 宏包选项,你可以在调用宏包的时候直接设置这些选项,也可以在调用宏包之后使用 |\xeCJKsetup| 来 +% 设置这些选项。 +% +% 有些选项或命令后面带有 \hypertarget{expstar}{\hyperlink{expstar}{$\star$}} 号,这表示这 +% 个选项或命令只能在导言区中使用,而 \hypertarget{rexpstar}{\hyperlink{rexpstar}{\ding{73}}} +% 号则表示这个选项或命令只能在导言区使用,并且只影响随后定义的 CJK 字体。其余不带特殊标记的 +% 选项或命令,如果没有特别说明,可以在导言区或正文中使用。 +% +% \begin{function}{\xeCJKsetup} +% \begin{syntax} +% \cs{xeCJKsetup} \argbrace{\meta{key1}=\meta{var1}, \meta{key2}=\meta{var2}, ...} +% \end{syntax} +% 其中 \meta{key1}, \meta{key2} 是设置选项,而 \meta{val1}, \meta{val2} 则是对应选项的 +% 设置内容。多个选项可以在一个语句中完成设置。例如 +% \begin{verbatim} +% \usepackage[PunctStyle=kaiming]{xeCJK} +% \end{verbatim} +% 等价于 +% \begin{verbatim} +% \usepackage{xeCJK} +% ...... +% \xeCJKsetup{PunctStyle=kaiming} +% \end{verbatim} +% \end{function} +% +% \subsection{宏包选项}\label{sec:xeCJK-opt} +% +% 下列选项使用加粗的形式来表示 \pkg{xeCJK} 的默认设置。 +% +% \begin{function}{xeCJKactive} +% \begin{syntax} +% xeCJKactive = \meta{\TTF} +% \end{syntax} +% 打开/关闭对中文的特殊处理。 +% \end{function} +% +% \begin{function}[EXP]{CJKnumber} +% \begin{syntax} +% CJKnumber = \meta{\TFF} +% \end{syntax} +% 是否使用 \pkg{CJKnumb} 宏包。请注意,为了与 \pkg{CJKnumb} 兼容,\pkg{xeCJK} 修改了 +% 它的一些内部命令,所以这个选项需要在调用 \pkg{xeCJK} 时设置,而不能通过 |\xeCJKsetup| +% 来设置它。 +% \end{function} +% +% \begin{function}[EXP]{indentfirst} +% \begin{syntax} +% indentfirst = \meta{\TTF} +% \end{syntax} +% 跟在章节标题后面的第一段首行是否缩进。这个选项需要在调用 \pkg{xeCJK} 时设置,不能 +% 通过 |\xeCJKsetup| 来设置它。\pkg{xeCJK} 宏包中只有 |indentfirst| 和 |CJKnumber| +% 这两个选项,不能通过 |\xeCJKsetup| 来设置。 +% \end{function} +% +% \begin{function}{CJKspace} +% \begin{syntax} +% CJKspace = \meta{\TFF} +% \end{syntax} +% 缺省状态下,\pkg{xeCJK} 会忽略 CJK 文字之间的空格,使用这一选项来保留它们之间的空格。 +% \end{function} +% +% \begin{function}[EXP]{CJKmath} +% \begin{syntax} +% CJKmath = \meta{\TFF} +% \end{syntax} +% 是否支持在数学环境中直接输入 CJK 字符。使用这个选项后,可以直接在数学环境中 +% 输出 CJK 字符。 +% \end{function} +% +% \begin{function}{CJKglue} +% \begin{syntax} +% CJKglue = \argbrace{\cs{hspace}\argbrace{0pt plus .08\cs{baselineskip}}} +% \end{syntax} +% 设置 CJK 文字之间插入的 |glue|,上边是 \pkg{xeCJK} 的默认值。一般来说,除非有 +% 特殊需要(例如,改变文字间距等),否则不需要设置这个选项,使用默认值即可。如果要设置 +% 这个选项,为了行末的对齐,设置的 |glue| 最好有一定的弹性。 +% \end{function} +% +% \begin{function}{CJKecglue} +% \begin{syntax} +% CJKecglue = \argbrace{\ } +% \end{syntax} +% 设置 CJK 文字与西文、CJK 文字与行内数学公式之间的间距,默认值是一个空格。使用这个 +% 选项设置的 |glue| 最好也要用一定的弹性。请注意,这里设置的 |glue| 只影响 +% \pkg{xeCJK} 根据需要自动添加的空白,源文件中直接输入的 CJK 文字与西文之间的空格不 +% 受影响(直接输出)。有时候 \pkg{xeCJK} 可能不能正确地调整间距,需要手动加空格。 +% \end{function} +% +% \begin{function}{xCJKecglue} +% \begin{syntax} +% xCJKecglue = \meta{\TFF\orvar{}glue} +% \end{syntax} +% 缺省状态下,\pkg{xeCJK} 不对源文件中直接输入的 CJK 文字与西文之间的空格进行调整,如 +% 果需要调整,请使用这个选项。如果使用这个选项,将使用 |CJKecglue| 替换源文件中直接输 +% 入的 CJK 文字与西文之间的空格。 +% \end{function} +% +% \begin{function}{CheckSingle} +% \begin{syntax} +% CheckSingle = \meta{\TFF} +% \end{syntax} +% 是否避免单个 CJK 文字单独占一个段落的最后一行。 +% \end{function} +% +% \begin{function}{InlineEnv,InlineEnv+,InlineEnv-} +% \begin{syntax} +% CheckSingle = \argbrace{env1, env2, env3, ...} +% \end{syntax} +% 在使用 |CheckSingle| 选项的时候,\pkg{xeCJK} 会将 CJK 文字后接着的 \LaTeX 环境的 +% 开始 |\begin{...}| 和结束 |\end{...}| 视为断行的地方,如果有某些特殊 +% 的 \LaTeX 环境没有造成断行,可以使用这个选项来声明它,以便 |CheckSingle| 能正确识别。 +% \end{function} +% +% \begin{function}{AutoFallBack} +% \begin{syntax} +% AutoFallBack = \meta{\TFF} +% \end{syntax} +% 当文档中有个别生僻字时,可以使用这个选项,自动使用预先设置好的后备字体来输出这些生僻 +% 字。后备字体的设置方法将在 \ref{sec:xeCJK-font} 节中介绍。 +% \end{function} +% +% \begin{function}[rEXP]{AutoFakeBold} +% \begin{syntax} +% AutoFakeBold = \meta{\TFF\orvar{}数字} +% \end{syntax} +% 全局设定当没有声明对应的粗体时,是否使用\textbf{\CJKfontspec[AutoFakeBold]{Adobe Song Std}伪粗体}; +% 当输入的是数字时,将使用伪粗体,并将使用输入的数字作为伪粗体的默认粗细程度。 +% \end{function} +% +% \begin{function}[rEXP]{AutoFakeSlant} +% \begin{syntax} +% AutoFakeSlant = \meta{\TFF\orvar{}数字} +% \end{syntax} +% 全局设定当没有声明对应的斜体时,是否使用\textit{\CJKfontspec[AutoFakeSlant]{Adobe Song Std}伪斜体}; +% 当输入的是数字时,将使用伪斜体,并将使用输入的数字作为伪斜体的默认倾斜程度。 +% \end{function} +% +% \begin{function}[rEXP]{EmboldenFactor} +% \begin{syntax} +% EmboldenFactor = \meta{数字\orvar\defaultvar{4}} +% \end{syntax} +% 设置伪粗体的默认粗细程度。 +% \end{function} +% +% \begin{function}[rEXP]{SlantFactor} +% \begin{syntax} +% SlantFactor = \meta{数字\orvar\defaultvar{0.167}} +% \end{syntax} +% 设置伪斜体的粗细程度,范围是 $-0.999 \sim 0.999$。 +% \end{function} +% +% \begin{function}{PunctStyle} +% \begin{syntax} +% PunctStyle = \meta{\defaultvar{quanjiao}\orvar{}banjiao\orvar{}kaiming\orvar{}hangmobanjiao\orvar{}CCT\orvar{}plain} +% \end{syntax} +% 设置标点处理格式,有效值分别为 +% \begin{itemize}[font=\ttfamily,labelsep=1em] +% \item[quanjiao] 全角式:所有标点占一个汉字宽度,相邻两个标点占 1.5 汉字宽度; +% \item[banjiao] 半角式:所有标点占半个汉字宽度; +% \item[kaiming] 开明式:句末点号用全角,其他半角; +% \item[hangmobanjiao] 行末半角式:所有标点占一个汉字宽度,行首行末对齐; +% \item[CCT] CCT 格式; +% \item[plain] 原样(不调整标点间距)。 +% \end{itemize} +% \end{function} +% +% \begin{function}[EXP]{KaiMingPunct,KaiMingPunct+,KaiMingPunct-} +% \begin{syntax} +% KaiMingPunct = \meta{\defaultvar{ . 。? !}} +% \end{syntax} +% 设置开明(|kaiming|)标点处理格式时的句末点号,|KaiMingPunct| 后带的 |+| 与 |-| +% 分别表示从已有的开明句末点号中增加或减少标点。 +% \end{function} +% +% \begin{function}[EXP]{LongPunct,LongPunct+,LongPunct-} +% \begin{syntax} +% LongPunct = \meta{\defaultvar{ — ‥ … ─ }} +% \end{syntax} +% 设置长标点,例如破折号“——”与省略号“……”,允许在长标点前后 +% 断行,但是禁止在它们之间断行。 +% \end{function} +% +% \begin{function}[EXP]{MiddlePunct,MiddlePunct+,MiddlePunct-} +% \begin{syntax} +% MiddlePunct = \meta{\defaultvar{ · · ・ }} +% \end{syntax} +% 设置居中显示的标点,例如间隔号“\textbf{·}”。对于在 CJK 文字之间的居中标点, +% \pkg{xeCJK} 会根据不同的标点处理格式,调整居中标点与前后文字之间的空白,保证 +% 其确实居中。对于行末出现的居中标点,允许在其后面断行,但禁止在它前面断行。 +% \end{function} +% +% \begin{function}[EXP]{PunctWidth} +% \begin{syntax} +% PunctWidth = \Arg{dimen} +% \end{syntax} +% 缺省状态下,\pkg{xeCJK} 会根据所选择的标点处理格式自动计算标点所占的宽度,如果对缺 +% 省设置不满意,可以通过这一选项来改变它。为了使得标点所占的宽度能够适应字体大小的变化, +% 这里设置的 |dimen| 的单位最好用 |em| 等相对距离单位,而不建议使用诸如 |pt| 之类的 +% 绝对距离单位。这里的设置对除了 |plain| 以外的所有标点处理格式都有效。同时,这里的 +% 设置对所有的 CJK 标点都生效,如果只要设置部分标点,请使用 \ref{sec:xeCJK-ps} 节的 +% |\xeCJKsetwidth|。 +% \end{function} +% +% \begin{function}{AllowBreakBetweenPuncts} +% \begin{syntax} +% AllowBreakBetweenPuncts = \meta{\TFF} +% \end{syntax} +% 缺省状态下,\pkg{xeCJK} 禁止在相邻 CJK 右标点和 CJK 左标点之间换行,可以使用 +% 这一选项改变这一设置。 +% \end{function} +% +% \subsection{CJK 字体族声明方式}\label{sec:xeCJK-font} +% +% \begin{function}[EXP]{\setCJKmainfont} +% \begin{syntax} +% \cs{setCJKmainfont} \oarg{font features} \Arg{font name} +% \end{syntax} +% 设置正文罗马族的 CJK 字体,最后两个参数的意义请参考 \pkg{fontspec} 宏包。影响 +% |\rmfamily| 和 |\textrm| 的字体。需要说明的是 \pkg{xeCJK} 修改了 +% |AutoFakeBold| 和 |AutoFakeSlant| 选项,以便配合全局伪粗体和伪斜体的设定。 +% \end{function} +% +% \begin{function}{AutoFakeBold,AutoFakeSlant} +% \begin{syntax} +% AutoFakeBold = \meta{\TF\orvar{}数字} +% AutoFakeSlant = \meta{\TF\orvar{}数字} +% \end{syntax} +% 局部设置当前字体族的伪粗和伪斜属性。如果没有在局部给出这些选项,将使用全局设定。 +% \end{function} +% +% \begin{function}[EXP]{\setCJKsansfont} +% \begin{syntax} +% \cs{setCJKsansfont} \oarg{font features} \Arg{font name} +% \end{syntax} +% 设置正文无衬线族的 CJK 字体,影响 |\sffamily| 和 |\textsf| 的字体。 +% \end{function} +% +% \begin{function}[EXP]{\setCJKmonofont} +% \begin{syntax} +% \cs{setCJKmonofont} \oarg{font features} \Arg{font name} +% \end{syntax} +% 设置正文等宽族的 CJK 字体,影响 |\ttfamily| 和 |\texttt| 的字体。为了有利于等宽 +% 字体的代码对齐等情形,\pkg{xeCJK} 在 \meta{font features} 里增加了 |Mono| 这个选项。 +% \end{function} +% +% \begin{function}{Mono} +% \begin{syntax} +% Mono = \meta{Scale\orvar{}Exspace} +% \end{syntax} +% 有效值仅为 |Scale| 或 |Exspace|。分别表示使用放缩的方式或改变间距的方式,让 CJK +% 字符的宽度等于西文字体中两个空格的宽度。 +% \end{function} +% +% \begin{function}{\CJKfixedspacing,\CJKflexiblespacing} +% \begin{syntax} +% \cs{CJKfixedspacing} +% \cs{CJKflexiblespacing} +% \end{syntax} +% |\CJKfixedspacing| 命令设置固定字距和不压缩标点格式,符合上面 |Mono=Exspace| 选 +% 项的意义。|\CJKflexiblespacing| 命令恢复可伸缩的字距和标点压缩。抄录 |(verbatim)| +% 环境将自动使用 |\CJKfixedspacing| 的效果。 +% \end{function} +% +% \begin{function}{\setCJKmonoscale,\setCJKmonoexspace} +% \begin{syntax} +% \cs{setCJKmonoscale} +% \cs{setCJKmonoexspace} +% \end{syntax} +% |\setCJKmonoscale| 和 |\setCJKmonoexspace| 命令分别计算并设置当前字号下西文等宽 +% 字体与 CJK 字体的放缩比例和字距,以符合上面所说的 |Mono=Scale| 与 |Mono=Exspace| +% 选项的意义。在字号改变时,应该使用两个命令之一,重新计算相关参数;但注意两个命令不 +% 能同时使用。 +% \end{function} +% +% \begin{function}[EXP]{\setCJKfamilyfont} +% \begin{syntax} +% \cs{setCJKfamilyfont} \Arg{family} \oarg{font features} \Arg{font name} +% \end{syntax} +% 声明新的 CJK 字体族 \meta{family} 并指定字体。 +% \end{function} +% +% \begin{function}{\CJKfamily} +% \begin{syntax} +% \cs{CJKfamily} \Arg{family} +% \end{syntax} +% 用于在文档中切换 |CJK| 字体族,\meta{family} 必须预先声明。 +% \end{function} +% +% \begin{function}[EXP]{\newCJKfontfamily} +% \begin{syntax} +% \cs{newCJKfontfamily} \oarg{family} \cs{\meta{font-switch}} \oarg{font features} \Arg{font name} +% \end{syntax} +% 声明新的 CJK 字体族 \meta{family} 并指定字体,并定义 \cs{\meta{font-switch}},在 +% 文档中可以使用它来切换 CJK 字体族。可以不必指定 \meta{family},这时候 \meta{family} +% 将等于 \meta{font-switch}。事实上,|\newCJKfontfamily| 是 |\setCJKfamilyfont| 和 +% |\CJKfamily| 的合并。例如 +% \begin{verbatim} +% \newCJKfontfamily[song]\songti{SimSun} +% \end{verbatim} +% 等价于 +% \begin{verbatim} +% \setCJKfamilyfont{song}{SimSun} +% \newcommand\songti{\CJKfamily{song}} +% \end{verbatim} +% \end{function} +% +% \begin{function}{\CJKfontspec} +% \begin{syntax} +% \cs{CJKfontspec} \oarg{font features} \Arg{font name} +% \end{syntax} +% 在文档中随机定义新的 CJK 字体族,并马上使用它。 +% \end{function} +% +% \begin{function}[rEXP]{\defaultCJKfontfeatures} +% \begin{syntax} +% \cs{defaultCJKfontfeatures} \Arg{font features} +% \end{syntax} +% 全局设置 CJK 字体族的默认选项。例如,使用 +% \begin{verbatim} +% \defaultCJKfontfeatures{Scale=0.962216} +% \end{verbatim} +% 可以将全部 CJK 字体缩小为 |0.962216|。 +% \end{function} +% +% \begin{function}{\addCJKfontfeatures} +% \begin{syntax} +% \cs{addCJKfontfeatures} \Arg{font features} +% \end{syntax} +% 临时增加当前使用的 CJK 字体的选项。例如,使用 +% \begin{verbatim} +% \addCJKfontfeatures{Scale=1.1} +% \end{verbatim} +% 可以将文档中当前使用的 CJK 字体放大为 |1.1|。 +% \end{function} +% +% \begin{function}{\CJKrmdefault} +% 保存 |\rmfamily| 所使用的 CJK 字体族,默认值是 |rm|。类似西文字体的 |\rmdefault|。 +% \end{function} +% +% \begin{function}{\CJKsfdefault} +% 保存 |\sffamily| 所使用的 CJK 字体族,默认值是 |sf|。类似西文字体的 |\sfdefault|。 +% \end{function} +% +% \begin{function}{\CJKttdefault} +% 保存 |\ttfamily| 所使用的 CJK 字体族,默认值是 |tt|。类似西文字体的 |\ttdefault|。 +% \end{function} +% +% \begin{function}{\CJKfamilydefault} +% 保存 |\normalfont| 所使用的 CJK 字体族,默认值是 |\CJKrmdefault|。类似西文字 +% 体的 |\familydefault|。可以通过更改它来改变文档的默认 CJK 字体族。例如,使用 +% \begin{verbatim} +% \renewcommand\familydefault{\sfdefault} +% \renewcommand\CJKfamilydefault{\CJKsfdefault} +% \end{verbatim} +% 可以将全文的 CJK 和西文默认字体改为无衬线字体族。 +% \end{function} +% +% \begin{function}[EXP]{\setCJKmathfont} +% \begin{syntax} +% \cs{setCJKmathfont} \oarg{font features} \Arg{font name} +% \end{syntax} +% 设置数学公式中的 CJK 字体族。如果使用了 |CJKmath| 选项,但是没有使用 +% |\setCJKmathfont| 设置数学公式中的 CJK 字体,那么将使用 |\CJKfamilydefault| +% 作为数学公式中的 CJK 字体。 +% \end{function} +% +% \begin{function}[EXP]{\setCJKfallbackfamilyfont} +% \begin{syntax} +% \cs{setCJKfallbackfamilyfont} \Arg{family} \oarg{font features} \Arg{font name} +% \end{syntax} +% 设置 CJK 字体族 \meta{family} 的备用字体。例如,使用 +% \begin{verbatim} +% \setCJKmainfont{SimSun} +% \setCJKfallbackfamilyfont{\CJKrmdefault}{SimSun-ExtB} +% \end{verbatim} +% 可以将 |SimSun-ExtB| 作为 |SimSun| 的备用字体。 +% \end{function} +% +% \begin{function}{FallBack} +% \begin{syntax} +% FallBack = \argbrace{\oarg{font features}\Arg{font name}} +% \end{syntax} +% \pkg{xeCJK} 在 \meta{font features} 里增加了 |FallBack| 这个选项。用来在声明主 +% 字体的时候,同时设置备用字体。例如,上面的例子等价于: +% \begin{verbatim} +% \setCJKmainfont[FallBack=SimSun-ExtB]{SimSun} +% \end{verbatim} +% 如果 |FallBack| 的值为空,将设置的是备用字体。例如, +% \begin{verbatim} +% \setCJKmainfont[FallBack,AutoFakeBold,Scale=.97]{SimSun-ExtB} +% \end{verbatim} +% 等价于 +% \begin{verbatim} +% \setCJKfallbackfamilyfont{\CJKrmdefault}[AutoFakeBold,Scale=.97]{SimSun-ExtB} +% \end{verbatim} +% \end{function} +% +% \begin{function}[EXP]{\setCJKfallbackfamilyfont} +% \begin{syntax} +% \cs{setCJKfallbackfamilyfont} \Arg{family} \oarg{common font features} +% \ \char`\{ +% \ \argbrace{\oarg{font features 1} \Arg{font name 1}} , +% \ \argbrace{\oarg{font features 2} \Arg{font name 2}} , +% \ ...... +% \ \char`\} +% \end{syntax} +% |\setCJKfallbackfamilyfont| 还可以用于设置多层的备用字体。例如,使用 +% \begin{verbatim} +% \setCJKmainfont[AutoFakeBold,AutoFakeSlant]{KaiTi_GB2312} +% \setCJKfallbackfamilyfont{\CJKrmdefault}[AutoFakeSlant] +% { [BoldFont=SimHei]{SimSun} , +% [AutoFakeBold] {SimSun-ExtB} } +% \end{verbatim} +% 之后,就设置了 |SimSun| 是 |KaiTi_GB2312| 的备用字体,而 |SimSun-ExtB| 是 +% |SimSun| 的备用字体。 +% \end{function} +% +% \subsection{CJK 分区字体设置}\label{sec:xeCJK-block} +% +% 众所周知,CJK 文字数量极其庞大,单一的字体不可能涵盖所有的 CJK 文字。\pkg{xeCJK} 可 +% 以在同一 CJK 字体族下,自动使用不同的字体输出 CJK 字符范围内不同区块里的文字。首先要 +% 声明 CJK 子分区。 +% +% \begin{function}[EXP]{\xeCJKDeclareSubCJKBlock} +% \begin{syntax} +% \cs{xeCJKDeclareSubCJKBlock} \Arg{block} \Arg{block range} +% \end{syntax} +% 其中 \meta{block range} 是逗号列表,可以是 CJK 字符的 |Unicode| 范围,也可以是单个字符 +% 的 |Unicode|。例如 +% \begin{verbatim} +% { `中 -> `文 , "3400 -> "4DBF , "5000 -> "7000 , `汉 , `字 , "3500 } +% \end{verbatim} +% 的形式。使用 +% \begin{verbatim} +% \xeCJKDeclareSubCJKBlock{SPUA}{ "E400 -> "E4DA , "E500 -> "E5E8 , "E600 -> "E6CE } +% \xeCJKDeclareSubCJKBlock{Ext-B}{ "20000 -> "2A6DF } +% \end{verbatim} +% 就声明了 |SPUA| 和 |Ext-B| 这两个个子分区。同时在 \ref{sec:xeCJK-font} 节介绍的 +% CJK 字体设置命令的 \meta{font features} 里新建了 |SPUA| 和 |Ext-B| 这两个选项。 +% 新建的这两个选项的使用方法跟 \ref{sec:xeCJK-font} 介绍的 |FallBack| 类似。可以 +% 通过它们来设置字体。例如,使用 +% \begin{verbatim} +% \setCJKmainfont[SPUA=SunmanPUA,Ext-B=SimSun-ExtB]{SimSun} +% \end{verbatim} +% 就设置了文档的主字体是 |SimSun|,|SPUA| 分区的字体是 |SunmanPUA|,而 |Ext-B| 分区 +% 的字体是 |SimSun-ExtB|。 +% +% |\xeCJKDeclareSubCJKBlock| 应该在声明所有的 CJK 字体族之前使用。如果有某个 CJK 字 +% 体族没有设置 \meta{block} 选项,将使用 |\CJKfamilydefault| 的 \meta{block} 选项 +% 作为该 CJK 字体族的 \meta{block} 选项。如果希望在使用某 CJK 字体族时,不在 CJK 主 +% 分区与 \meta{block} 之间切换字体,可以使用 \meta{block}|=*| 选项。 +% \end{function} +% +% \begin{function}{\xeCJKCancelSubCJKBlock} +% \begin{syntax} +% \cs{xeCJKCancelSubCJKBlock} \Arg{block1,block2,...} +% \end{syntax} +% 在文档中取消对 |CJK| 分区的声明。 +% \end{function} +% +% \begin{function}{\xeCJKRestoreSubCJKBlock} +% \begin{syntax} +% \cs{xeCJKRestoreSubCJKBlock} \Arg{block1,block2,...} +% \end{syntax} +% 在文档中恢复对 |CJK| 分区的声明。 +% \end{function} +% +% \subsection{设置 CJK 字符范围} +% +% \begin{function}[EXP]{\xeCJKDeclareCharClass} +% \begin{syntax} +% \cs{xeCJKDeclareCharClass} \Arg{class} \Arg{class range} +% \end{syntax} +% \meta{class range} 的格式和 \ref{sec:xeCJK-block} 节的 \meta{block range} 相同。 +% \meta{class} 的有效值见源代码(第 \ref{sec:xeCJK-class-set} 节)。\pkg{xeCJK} 已 +% 经支持 |Unicode| 中所有 CJK 文字和标点。一般来说,不要轻易改变字符类别。 +% \end{function} +% +% \begin{function}[EXP]{\xeCJKResetPunctClass} +% \begin{syntax} +% \cs{xeCJKResetPunctClass} +% \end{syntax} +% 用于重置标点符号所属的字符类。使用 |\xeCJKDeclareCharClass| 更改字符类别之后,为 +% 了确保标点处理的正确性,应该在它之后使用 |\xeCJKResetPunctClass|。 +% \end{function} +% +% \begin{function}{\normalspacedchars} +% \begin{syntax} +% \cs{normalspacedchars} \Arg{char list} +% \end{syntax} +% 在 \meta{char list} 中出现的字符两端不自动添加空格,默认设置是 |/|。 +% \end{function} +% +% \subsection{设置标点宽度和间距}\label{sec:xeCJK-ps} +% +% 这里的设置对除了 |plain| 以外的所有标点处理格式都有效。 +% +% \begin{function}[EXP]{\xeCJKsetwidth} +% \begin{syntax} +% \cs{xeCJKsetwidth} \Arg{标点列表} \Arg{dimen} +% \end{syntax} +% \meta{标点列表}可以是单个标点,也可以是多个标点。例如, +% \begin{verbatim} +% \xeCJKsetwidth{。?}{0.7em} +% \end{verbatim} +% 将设置句号和问号所占的宽度为 |0.7em|。 +% \end{function} +% +% \begin{function}[EXP]{\xeCJKsetkern} +% \begin{syntax} +% \cs{xeCJKsetkern} \Arg{标点1} \Arg{标点2} \Arg{dimen} +% \end{syntax} +% \pkg{xeCJK} 会根据选定的标点处理格式自动调整相邻两个 |CJK| 标点的距离。如果对缺省 +% 配置不满意,可以使用此命令设置两个标点之间的距离。例如, +% \begin{verbatim} +% \xeCJKsetkern{:}{“}{0.3em} +% \end{verbatim} +% \end{function} % -% 设置标点格式,有效值分别为 -% -% \begin{tabular}{ll} -% punct style & \\ -% \textcolor{parametercolor}{banjiao} & 半角式:所有标点占半个汉字宽度。 \\ -% \textcolor{parametercolor}{quanjiao} & 全角式:所有标点占一个汉字宽度,相邻两个标点占1.5汉字宽度。\\ -% \textcolor{parametercolor}{kaiming} & 开明式:句末点号用全角,其他半角。\\ -% \textcolor{parametercolor}{hangmobanjiao}& 行末半角式:所有标点占一个汉字宽度,行首行末对齐。\\ -% \textcolor{parametercolor}{CCT} & CCT格式\\ -% \textcolor{parametercolor}{plain} & 原样(不调整标点间距) -% \end{tabular} -% -% -% -% \begin{decl} -% \defmacro{\xeCJKallowbreakbetweenpuncts} \\ -% \defmacro{\xeCJKnobreakbetweenpuncts} -% \end{decl} -% -% 缺省状态下,\xeCJK\ 禁止在相邻的标点间换行。 使用 -% -% \defmacro{\xeCJKallowbreakbetweenpuncts}\newline -% 改变这一设置。 +% \section{兼容性} % -% \begin{decl} -% \defmacro{\xeCJKsetslantfactor}\arg{slant factor}\\ -% \defmacro{\xeCJKsetemboldenfactor}\arg{embolden factor} -% \end{decl} -% 分别设置斜体和粗体的倾斜和粗细程度。 -% 其中 slant factor 的范围为 -0.999 $\sim$ 0.999. 缺省设置为 +% 为了与 \pkg{CJKnumb} 和 \pkg{CJKulem} 宏包兼容,\pkg{xeCJK} 使用并重新定义了 +% \pkg{CJK} 宏包的部分宏命令,如 |\CJKfamily|、|\CJKsymbol| 和 |\CJKpunctsymbol| 等。 +% 需要指出,\pkg{xeCJK} 不需要 \pkg{CJK} 的支持,并且 \pkg{xeCJK} 自动禁止在它之后载入 +% \pkg{CJK} 宏包。 % -% \begin{verbatim} -% \xeCJKsetslantfactor{0.17} -% \xeCJKsetemboldenfactor{4} -% \end{verbatim} +% 可以在 \pkg{xeCJK} 之后载入 \pkg{CJKfntef} 宏包,以实现汉字加点等。 % -% 注意,这两个宏命令仅对随后定义的 CJK 字体有效。 +% \pkg{xeCJK} 依赖 \XeTeX 的 |\XeTeXinterchartoks| 机制,与使用相同机制的宏包(例如 +% \pkg{polyglossia})会存在大小不一的冲突。 % % -% \begin{decl} -% \defmacro{\CJKnospace}\\ -% \defmacro{\CJKspace} -% \end{decl} -% \verb+\CJKnospace+ 忽略 CJK 文字之间的空格,这是默认行为,与 \verb+nospace+ -% 选项相同。\verb+\CJKspace+ 保留 CJK 文字之间的空格,但仍然忽略文字与全角标点 -% 间的空格,与宏包 \verb+space+ 选项相同。 +%\end{documentation} % % -% \begin{decl} -% \defmacro{\CJKsetecglue} -% \end{decl} +%\begin{implementation} % +% \section{\pkg{xeCJK} 代码实现} % +% \begin{macrocode} +%<*package> +% \end{macrocode} % -% \defmacro{\CJKsetecglue}: 设置中英文间距. 缺省值为\defmacro{\CJKsetecglue\{ \}}. -% 注意: 这个宏命令仅仅影响自动添加的空格. 源文件中直接输入的中英文之间的空格不受影响(直接输出). -% \bgroup\let\CJKecglue\relax -% \begin{verbatim} -% 这是 English 中文 \textit{Chinese} 中文 \LaTeX\ -% 中文\textbf{字体} a {\bfseries 数学} $c$ $d$-th\par -% 这是English中文\textit{Chinese}中文\LaTeX\ -% 中文\textbf{字体}a{\bfseries 数学}$c$ $d$-th\par -% \end{verbatim} -% \egroup +% \begin{macrocode} +\RequirePackage{xparse} +\RequirePackage{l3keys2e} +\ProvidesExplPackage {xeCJK} {2012/05/06} {3.0.4} + {package for typesetting CJK scripts with XeLaTeX} +% \end{macrocode} % -% \noindent -% 排版效果: +% \begin{macro}[aux] +% {\xeCJK_msg_new:nn ,\xeCJK_error:n,\xeCJK_error:nx, +% \xeCJK_warning:nx,\xeCJK_info:nx,\xeCJK_info:nxx} +% \begin{macrocode} +\cs_new_nopar:Npn \xeCJK_msg_new:nn { \msg_new:nnn { xeCJK } } +\cs_new_nopar:Npn \xeCJK_error:n { \msg_error:nn { xeCJK } } +\cs_new_nopar:Npn \xeCJK_error:nx { \msg_error:nnx { xeCJK } } +\cs_new_nopar:Npn \xeCJK_warning:n { \msg_warning:nn { xeCJK } } +\cs_new_nopar:Npn \xeCJK_warning:nx { \msg_warning:nnx { xeCJK } } +\cs_new_nopar:Npn \xeCJK_info:nx { \msg_info:nnx { xeCJK } } +\cs_new_nopar:Npn \xeCJK_info:nxx { \msg_info:nnxx { xeCJK } } +% \end{macrocode} +% \end{macro} % -% 这是 English 中文 \textit{Chinese} 中文 \LaTeX\ -% 中文\textbf{字体} a {\bfseries 数学} $c$ $d$-th\par -% 这是English中文\textit{Chinese}中文\LaTeX\ -% 中文\textbf{字体}a{\bfseries 数学}$c$ $d$-th\par +% \pkg{xeCJK} 必须使用 \XeTeX 引擎的支持。 +% \begin{macrocode} +\msg_new:nnn {xeCJK} { Require-XeTeX } + { + The~xeCJK~package~requires~XeTeX~to~function.\\\\ + You~must~change~your~typesetting~engine~to~"xelatex" \\ + instead~of~plain~"latex"~or~"pdflatex"~or~"lualatex". + } +\xetex_if_engine:F { \msg_critical:nn { xeCJK } { Require-XeTeX } } +% \end{macrocode} % -% 说明: -% \begin{enumerate} +% |\XeTeXglyphbouds| 可以得到一个字符的左右边距,用于标点压缩。 +% \begin{macrocode} +\xeCJK_msg_new:nn { XeTeX-too-old } + { + \token_to_str:N \XeTeXglyphbounds\c_space_tl is~not~defined.\\\\ + You~have~to~update~XeTeX~to~the~version~0.9995.0~or~later. + } +\cs_if_free:NT \XeTeXglyphbounds + { + \xeCJK_error:n { XeTeX-too-old } + \AtBeginDocument { \punctstyle { plain } } + } +% \end{macrocode} % -% \item 中英文之间的空格会保留(不能调整), -% 但若没有空格,则会根据需要添加(见上面的例子)。 +% 抑制 |BOM|。 +% \begin{macrocode} +\char_set_catcode_ignore:n { "FEFF } +% \end{macrocode} % -% 有时可能无效, -% 解决方案是手动加空格。 -%\end{enumerate} +% \begin{macro}{xeCJKactive} +% \pkg{xeCJK} 功能开关。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { + xeCJKactive .choice:, + xeCJKactive / true .code:n = { \makexeCJKactive } , + xeCJKactive / false .code:n = { \makexeCJKinactive } , + xeCJKactive .default:n = { true }, + } +% \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\makexeCJKactive, \makexeCJKinactive} +% \begin{macrocode} +\NewDocumentCommand \makexeCJKactive { } { \XeTeXinterchartokenstate = \c_one } +\NewDocumentCommand \makexeCJKinactive { } { \XeTeXinterchartokenstate = \c_zero } +% \end{macrocode} +% \end{macro} % -% \begin{decl} -% \defmacro{\xeCJKenablefallback}\\ -% \defmacro{\xeCJKdisablefallback} -% \end{decl} -% 打开或关闭备用字体功能。 +% \subsection{字符类别设定}\label{sec:xeCJK-class-set} % +% \pkg{xeCJK} 需要以下字符类别用于字符输出。其中 |Default|、|CJK|、|FullLeft|、 +% |FullRight|、|Boundary| 为 \XeTeX\ 中预定义的类别,\pkg{xeCJK} 新增加了\ +% |HalfLeft|、|HalfRight|、|NormalSpace|。 +% \begin{center}\punctstyle{plain} +% \begin{tabular}{cll} +% \toprule +% 类别 & 说明 & 例子 \\ \midrule +% |Default| & 西文一般符号 & abc123 \\ +% |CJK| & CJK 表意符号 & 汉字ぁぃぅ \\ +% |FullLeft| & 全角左标点 & (《:“ \\ +% |FullRight| & 全角右标点 & ,。)》” \\ +% |HalfLeft| & 半角左标点 & ( [ \{ \\ +% |HalfRight| & 半角右标点 & , . ? ) ] \} \\ +% |NormalSpace| & 前后原始间距的符号 & / \\ +% |Boundary| & 边界 & 空格 \\ +% \bottomrule +% \end{tabular} +% \end{center} % -% \begin{decl} -% \defmacro{\xeCJKsetcharclass}\arg{first}\arg{last}\arg{class} -% \end{decl} +% \begin{macro}[internal,var] +% { \xeCJK_Default_class, \xeCJK_CJK_class, \xeCJK_FullLeft_class, +% \xeCJK_FullRight_class, \xeCJK_Boundary_class } +% 这五类是 \XeTeX\ 预定义的类别。 +% \begin{macrocode} +\int_const:Nn \xeCJK_Default_class { 0 } +\int_const:Nn \xeCJK_CJK_class { 1 } +\int_const:Nn \xeCJK_FullLeft_class { 2 } +\int_const:Nn \xeCJK_FullRight_class { 3 } +\int_const:Nn \xeCJK_Boundary_class { 255 } +% \end{macrocode} +% \end{macro} % -% 该命令将设定 Unicode 范围 \meta{first}--\meta{last} 的字符类别为 -% \meta{class}。 +% \begin{macro}[internal]{\xeCJK_new_class:n,\g_xeCJK_class_seq} +% 新建一个字符类别。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_new_class:n + { + \exp_after:wN \newXeTeXintercharclass \cs:w xeCJK_#1_class\cs_end: + \clist_gclear_new:c { g_xeCJK_#1_range_clist } + \seq_gput_right:Nv \g_xeCJK_class_seq { xeCJK_#1_class } + } +\seq_new:N \g_xeCJK_class_seq +% \end{macrocode} +% \end{macro} % -% 类别 0 表示一般西文符号,使用西文字体;类型 1 表示一般 CJK 表意符号,使用 -% CJK 字体。默认只将 Unicode 区的 CJK 文字和标点使用 CJK 字体,字符类别的详细 -% 说明及缺省状态下的设置见源代码第~\ref{sec:charclass}~节。 +% \begin{macro}[internal,var] +% { \xeCJK_HalfLeft_class, \xeCJK_HalfRight_class, \xeCJK_NormalSpace_class } +% 新增西文半角左/右标点和前后原始间距的符号类。 +% \begin{macrocode} +\xeCJK_new_class:n { HalfLeft } +\xeCJK_new_class:n { HalfRight } +\xeCJK_new_class:n { NormalSpace } +% \end{macrocode} +% \end{macro} % -% 例如,以下命令设置 0x0080 --- 0x2FFF 之间的字符为非 CJK 文字,而 0x20000 -% --- 0x30000 之间的为 CJK 文字: -% \begin{verbatim} -% \xeCJKsetcharclass{"80}{"2FFF}{0} -% \xeCJKsetcharclass{"20000}{"30000}{1} -% \end{verbatim} -% 注意:最后一个参数只能为 0 或 1,且设定对预定义的标点符号无效。不要轻易改变 -% 字符类别。 +% \begin{macro}[internal,var] +% {\g_xeCJK_base_class_clist,\g_xeCJK_CJK_class_clist,\g_xeCJK_CJK_class_prop} +% \begin{macrocode} +\clist_set:Nn \g_xeCJK_base_class_clist + { + Default, CJK, FullLeft, FullRight, Boundary, + HalfLeft, HalfRight, NormalSpace + } +\clist_map_inline:Nn \g_xeCJK_base_class_clist + { \clist_gclear_new:c { g_xeCJK_#1_range_clist } } +\clist_new:N \g_xeCJK_CJK_class_clist +\prop_new:N \g_xeCJK_CJK_class_prop +\cs_new_nopar:Nn \xeCJK_save_CJK_class:n + { + \clist_gput_right:Nx \g_xeCJK_CJK_class_clist {#1} + \prop_gput:Nvx \g_xeCJK_CJK_class_prop { xeCJK_#1_class } {#1} + } +\cs_generate_variant:Nn \prop_gput:Nnn { Nvx } +\clist_map_inline:nn { CJK, FullLeft, FullRight } { \xeCJK_save_CJK_class:n {#1} } +% \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\xeCJK_class_num:n} +% |#1| 为字符类别名称,用于取得字符类别对应的编号。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_class_num:n { \use:c { xeCJK_#1_class } } +% \end{macrocode} +% \end{macro} % -% \begin{decl} -% \defmacro{\xeCJKcaption}[\textcolor{optioncolor}{<encoding>}]\arg{caption} -% \end{decl} +% \begin{macro}[pTF,internal]{\tl_if_blank:x} +% \begin{macrocode} +\prg_set_conditional:Nnn \tl_if_blank:x { p , T , F , TF } + { + \if_int_compare:w \pdftex_strcmp:D { \c_empty_tl } {#1} = \c_zero + \prg_return_true: + \else: + \if_int_compare:w \pdftex_strcmp:D { \c_space_tl } {#1} = \c_zero + \prg_return_true: \else: \prg_return_false: \fi: + \fi: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xeCJKDeclareCharClass} +% \begin{macro}[aux]{\xeCJK_setcharclass_aux:Nn} +% 用于设置字符所属的类别,|#1| 为类别名称,|#2| 为字符的 |Unicode|,相邻字符用 +% 半角逗号隔开,支持类似 |"1100 -> "11FF| 起止范围的使用方式。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKDeclareCharClass { > { \TrimSpaces } m m } + { + \clist_gput_right:cx { g_xeCJK_#1_range_clist } {#2} + \clist_map_inline:xn {#2} + { + \str_if_eq:xxF {##1} { -> } + { + \xeCJK_setcharclass_aux:Nn \xeCJKsetcharclass {##1} + { \xeCJK_class_num:n {#1} } + } + } + } +\NewDocumentCommand \xeCJK_setcharclass_aux:Nn + { m > { \SplitArgument { 1 } { -> } } m } { #1 #2 } +\cs_generate_variant:Nn \clist_map_inline:nn { x } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJKsetcharclass} +% |#1| 和 |#2| 为字符类别起止的 |Unicode|,|#3| 为类别名称对应编号。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKsetcharclass { m m m } + { + \xeCJK_check_num_range:nnNN {#1} {#2} \l_tmpa_int \l_tmpb_int + \int_set:Nn \l_tmpc_int {#3} + \prop_if_in:NVTF \g_xeCJK_CJK_class_prop \l_tmpc_int + { \cs_set_eq:NN \xeCJK_set_catcode:n \char_set_catcode_other:n } + { \cs_set_eq:NN \xeCJK_set_catcode:n \use_none:n } + \loop + \xeCJK_set_catcode:n \l_tmpa_int + \XeTeXcharclass \l_tmpa_int = \l_tmpc_int + \if_int_compare:w \l_tmpa_int < \l_tmpb_int + \int_incr:N \l_tmpa_int + \repeat + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_check_num_range:nnNN} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_check_num_range:nnNN + { + \bool_if:nTF { \tl_if_blank_p:x {#1} || \tl_if_blank_p:x {#2} } + { + \int_set:Nn #3 { \tl_if_blank:xTF {#1} {#2} {#1} } + \int_set_eq:NN #3 #4 + } + { + \int_set:Nn #3 { \int_min:nn {#1} { \IfNoValueTF {#2} {#1} {#2} } } + \int_set:Nn #4 { \int_max:nn {#1} { \IfNoValueTF {#2} {#1} {#2} } } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xeCJKResetPunctClass} +% 用于重置标点符号所属的字符类。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKResetPunctClass { } + { + \xeCJKDeclareCharClass { HalfLeft } + { "28 , "2D , "5B , "60 , "7B } + \xeCJKDeclareCharClass { HalfRight } + { "21 , "22 , "25 , "27 , "29 , "2C , "2E , "3A , "3B , "3F , "5D , "7D , } + \xeCJKDeclareCharClass { FullLeft } + { + "2018 , "201C , "2116 , "3008 , "300A , "300C , "300E , "3010 , "3012 , + "3014 , "3016 , "3018 , "301A , "301D , "3036 , "E76C , "FE59 , "FE5B , + "FE5D , "FE5F , "FE60 , "FE69 , "FE6B , "FF03 , "FF04 , "FF08 , "FF20 , + "FF3B , "FF5B , "FFE0 , "FFE1 , "FFE5 , "FFE6 , + } + \xeCJKDeclareCharClass { FullRight } + { + "00B7 , "2019 , "201D , "2014 , "2025 , "2026 , "2030 , "2500 , "3001 , + "3002 , "3005 , "3006 , "3009 , "300B , "300D , "300F , "3011 , "3015 , + "3017 , "3019 , "301B , "301E , "301F , "3041 , "3043 , "3045 , "3047 , + "3049 , "3063 , "3083 , "3085 , "3087 , "308E , "309B , "309C , "309D , + "309E , "30A1 , "30A3 , "30A5 , "30A7 , "30A9 , "30C3 , "30E3 , "30E5 , + "30E7 , "30EE , "30F5 , "30F6 , "30FB , "30FC , "30FD , "30FE , "FE50 , + "FE51 , "FE52 , "FE54 , "FE55 , "FE56 , "FE57 , "FE5A , "FE5C , "FE5E , + "FE6A , "FF01 , "FF05 , "FF09 , "FF0C , "FF0E , "FF1A , "FF1B , "FF1F , + "FF3D , "FF5D , "FF61 , "FF63 , "FF64 , "FF65 , "FF67 , "FF68 , "FF69 , + "FF6A , "FF6B , "FF6C , "FF6D , "FF6E , "FF6F , "FF70 , "FF9E , "FF9F , + } + } +% \end{macrocode} +% \end{macro} % -% 与 \verb+\CJKcaption+ 类似,可选参数用以选择编码, 缺省为 UTF-8。 +% \hypertarget{CJKcharclass}{设置 CJK 文字的范围}。 +% \begin{macrocode} +\xeCJKDeclareCharClass { CJK } + { +% \end{macrocode} +% \begin{itemize} +% \item Hangul Jamo (谚文字母) +% \begin{macrocode} + "1100 -> "11FF , +% \end{macrocode} +% \item CJK Radicals Supplement (中日韩部首补充) +% \begin{macrocode} + "2E80 -> "2EFF , +% \end{macrocode} +% \item Kangxi Radicals (康熙部首) +% \begin{macrocode} + "2F00 -> "2FDF , +% \end{macrocode} +% \item Ideographic Description Characters (表意文字描述符) +% \begin{macrocode} + "2FF0 -> "2FFF , +% \end{macrocode} +% \item CJK Symbols and Punctuation (中日韩符号和标点) +% \begin{macrocode} + "3000 -> "303F , +% \end{macrocode} +% \item Hiragana (日文平假名) +% \begin{macrocode} + "3040 -> "309F , +% \end{macrocode} +% \item Katakana (日文片假名) +% \begin{macrocode} + "30A0 -> "30FF , +% \end{macrocode} +% \item Bopomofo (注音字母) +% \begin{macrocode} + "3100 -> "312F , +% \end{macrocode} +% \item Hangul Compatibility Jamo (谚文兼容字母) +% \begin{macrocode} + "3130 -> "318F , +% \end{macrocode} +% \item Kanbun (象形字注释标志) +% \begin{macrocode} + "3190 -> "319F , +% \end{macrocode} +% \item Bopomofo Extended (注音字母扩展) +% \begin{macrocode} + "31A0 -> "31BF , +% \end{macrocode} +% \item CJK Strokes (中日韩笔画) +% \begin{macrocode} + "31C0 -> "31EF , +% \end{macrocode} +% \item Katakana Phonetic Extensions (日文片假名语音扩展) +% \begin{macrocode} + "31F0 -> "31FF , +% \end{macrocode} +% \item Enclosed CJK Letters and Months (带圈中日韩字母和月份) +% \begin{macrocode} + "3200 -> "32FF , +% \end{macrocode} +% \item CJK Compatibility (中日韩兼容) +% \begin{macrocode} + "3300 -> "33FF , +% \end{macrocode} +% \item CJK Unified Ideographs Extension-A (中日韩统一表意文字扩展 A) +% \begin{macrocode} + "3400 -> "4DBF , +% \end{macrocode} +% \item Yijing Hexagrams Symbols (易经六十四卦符号) +% \begin{macrocode} + "4DC0 -> "4DFF , +% \end{macrocode} +% \item CJK Unified Ideographs (中日韩统一表意文字) +% \begin{macrocode} + "4E00 -> "9FFF , +% \end{macrocode} +% \item Yi Syllables (彝文音节) +% \begin{macrocode} + "A000 -> "A48F , +% \end{macrocode} +% \item Yi Radicals (彝文字根) +% \begin{macrocode} + "A490 -> "A4CF , +% \end{macrocode} +% \item Hangul Jamo Extended-A (谚文扩展 A) +% \begin{macrocode} + "A960 -> "A97F , +% \end{macrocode} +% \item Hangul Syllables (谚文音节) +% \begin{macrocode} + "AC00 -> "D7AF , +% \end{macrocode} +% \item Kana Supplement (日文假名增补) +% \begin{macrocode} + "B000 -> "B0FF , +% \end{macrocode} +% \item Hangul Jamo Extended-B (谚文扩展 B) +% \begin{macrocode} + "D7B0 -> "D7FF , +% \end{macrocode} +% \item CJK Compatibility Ideographs (中日韩兼容表意文字) +% \begin{macrocode} + "F900 -> "FAFF , +% \end{macrocode} +% \item CJK Compatibility Forms (中日韩兼容形式) +% \begin{macrocode} + "FE30 -> "FE4F , +% \end{macrocode} +% \item Halfwidth and Fullwidth Forms (半角及全角形式) +% \begin{macrocode} + "FF00 -> "FFEF , +% \end{macrocode} +% \item CJK Unified Ideographs Extension-B (中日韩统一表意文字扩展 B) +% \begin{macrocode} + "20000 -> "2A6DF , +% \end{macrocode} +% \item CJK Unified Ideographs Extension-C (中日韩统一表意文字扩展 C) +% \begin{macrocode} + "2A700 -> "2B73F , +% \end{macrocode} +% \item CJK Unified Ideographs Extension-D (中日韩统一表意文字扩展 D) +% \begin{macrocode} + "2B740 -> "2B81F , +% \end{macrocode} +% \item CJK Compatibility Ideographs Supplement (中日韩兼容表意文字增补) +% \begin{macrocode} + "2F800 -> "2FA1F , +% \end{macrocode} +% \end{itemize} +% \begin{macrocode} + } +% \end{macrocode} % -% \begin{decl} -% \defmacro{\xeCJKsetkern}\arg{标点1}\arg{标点2}\arg{kern} -% \end{decl} +% 重置标点符号的字符类。 +% \begin{macrocode} +\xeCJKResetPunctClass +% \end{macrocode} % -% 如果对缺省配置不满意,可以使用此命令设置两个标点之间的距离。例如, +% \begin{macro}{\normalspacedchars} +% 声明前后不加间距的字符。 +% \begin{macrocode} +\NewDocumentCommand \normalspacedchars { m } + { + \tl_map_inline:nn {#1} + { \XeTeXcharclass `##1 = \xeCJK_class_num:n { NormalSpace } } + } +\normalspacedchars{/} +% \end{macrocode} +% \end{macro} % -% \verb+\xeCJKsetkern{:}{“}{0.3em}+ +% \begin{macro}[internal]{\xeCJK_inter_class_toks:nnn,\xeCJK_inter_class_toks:nnc} +% 在相邻类别之间插入内容。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_inter_class_toks:nnn + { \XeTeXinterchartoks \xeCJK_class_num:n {#1} \xeCJK_class_num:n {#2} = {#3} } +\cs_generate_variant:Nn \xeCJK_inter_class_toks:nnn { nnc } +% \end{macrocode} +% \end{macro} % -% \begin{decl} -% \defmacro{\normalspacedchars}\arg{char list} -% \end{decl} -% 在<char list>中出现的字符两端不自动添加空格. +% \begin{macro}[internal]{\xeCJK_clear_inter_class_toks:nn} +% 清除相邻类别之间的内容。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_clear_inter_class_toks:nn + { + \XeTeXinterchartoks + \xeCJK_class_num:n {#1} \xeCJK_class_num:n {#2} = { \c_empty_tl } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_pre_inter_class_toks:nnn} +% 在相邻类别之间已有的内容前增加内容。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_pre_inter_class_toks:nnn + { + \use:x + { + \XeTeXinterchartoks \xeCJK_class_num:n {#1} \xeCJK_class_num:n {#2} = + { + \exp_not:n {#3} \tex_the:D \XeTeXinterchartoks + \xeCJK_class_num:n {#1} \xeCJK_class_num:n {#2} + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_app_inter_class_toks:nnn,\xeCJK_app_inter_class_toks:nnc} +% 在相邻类别之间已有的内容后追加内容。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_app_inter_class_toks:nnn + { + \use:x + { + \XeTeXinterchartoks \xeCJK_class_num:n {#1} \xeCJK_class_num:n {#2} = + { + \tex_the:D \XeTeXinterchartoks \xeCJK_class_num:n {#1} + \xeCJK_class_num:n {#2} \exp_not:n {#3} + } + } + } +\cs_generate_variant:Nn \xeCJK_app_inter_class_toks:nnn { nnc } +% \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\xeCJK_get_inter_class_toks:nn} +% 取出相邻类别之间的内容。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_get_inter_class_toks:nn + { + \tex_the:D \XeTeXinterchartoks \xeCJK_class_num:n {#1} \xeCJK_class_num:n {#2} + } +% \end{macrocode} +% \end{macro} % -% \begin{decl} -% \defmacro{\makexeCJKactive}\\ -% \defmacro{\makexeCJKinactive} -% \end{decl} -% 打开/关闭对中文的特殊处理. +% \begin{macro}[internal]{\xeCJK_copy_inter_class_toks:nnnn} +% 将 |#3| 和 |#4| 之间的内容复制到 |#1| 和 |#2| 之间。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_copy_inter_class_toks:nnnn + { + \use:x + { + \xeCJK_inter_class_toks:nnn {#1} {#2} + { \xeCJK_get_inter_class_toks:nn {#3} {#4} } + } + } +% \end{macrocode} +% \end{macro} % -% \section{兼容性} +% \begin{macro}[internal]{\xeCJK_clear_CJK_toks:} +% 清除边界与 CJK 文字、全角左右标点之间的内容。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_clear_CJK_toks: + { + \clist_map_inline:Nn \g_xeCJK_CJK_class_clist + { \xeCJK_clear_inter_class_toks:nn { Boundary } {##1} } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{字符输出规则} +% +% \begin{macrocode} +\clist_map_inline:nn { Default, HalfLeft, HalfRight, NormalSpace } + { + \clist_map_inline:nn { CJK, FullLeft, FullRight } + { + \xeCJK_inter_class_toks:nnn {#1} {##1} + { + \c_group_begin_token + \xeCJK_select_font: + \xeCJK_clear_inter_class_toks:nn {#1} {##1} + \xeCJK_clear_CJK_toks: + } + } + \xeCJK_app_inter_class_toks:nnn {#1} { CJK } { \CJKsymbol } + \clist_map_inline:nn { FullLeft, FullRight } + { \xeCJK_app_inter_class_toks:nnc {#1} {##1} { xeCJK_CJK_and_##1:N } } + \xeCJK_inter_class_toks:nnn { CJK } {#1} { \c_group_end_token } + \xeCJK_inter_class_toks:nnn { FullLeft } {#1} { \nobreak \c_group_end_token } + \xeCJK_inter_class_toks:nnn { FullRight } {#1} + { \xeCJK_after_FullRight: \c_group_end_token } + } +% \end{macrocode} % -% \subsection{CJKfntef} -% 可以在 \xeCJK\ 包之后调入 CJKfntef 宏包, 以实现汉字加点等。 +% \begin{macrocode} +\xeCJK_pre_inter_class_toks:nnn { Default } { CJK } { \CJKecglue } +% \end{macrocode} % -% \subsection{CJKnumber} +% \begin{macrocode} +\clist_map_inline:nn { Default, HalfLeft, NormalSpace } + { + \xeCJK_inter_class_toks:nnn { Boundary } {#1} + { + \int_compare:nNnTF \tex_lastkern:D = \c_one { \CJKecglue } + { \int_compare:nNnT \tex_lastkern:D = \c_two \xeCJK_space_or_xecglue: } + } + \str_if_eq:xxF {#1} { NormalSpace } + { \xeCJK_app_inter_class_toks:nnn { CJK } {#1} { \CJKecglue } } + } +% \end{macrocode} % -% \verb+\CJKnumber{12345}+: \CJKnumber{12345} +% \begin{macrocode} +\clist_map_inline:nn { Default, HalfRight, NormalSpace } + { + \xeCJK_inter_class_toks:nnn {#1} { Boundary } + { + \peek_catcode:NTF \c_space_token + { { \xeCJK_default_space_kern: } } { { \xeCJK_default_kern: } } + } + } +% \end{macrocode} % -% \subsection{CJK} -% 为了与 CJKnumb 和 CJKulem 包兼容,\xeCJK\ 重新定义了 CJK 包的部分宏命令,如 -% \verb+\CJKfamily+, \verb+\CJKsymbol+, \verb+\CJKpunctsymbol+ 等。 +% \begin{macrocode} +\xeCJK_inter_class_toks:nnn { Boundary } { CJK } { \xeCJK_Boundary_and_CJK: } +% \end{macrocode} +% +% \begin{macro}[internal]{\xeCJK_Boundary_and_CJK:} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_Boundary_and_CJK: + { + { + \bool_if:nTF + { + \int_compare_p:nNn \tex_lastkern:D = \c_one || + \int_compare_p:nNn \tex_lastkern:D = \c_two + } + { \CJKglue } + { + \bool_if:nTF + { + \int_compare_p:nNn \tex_lastkern:D = \c_three || + \int_compare_p:nNn \etex_lastnodetype:D = \c_ten || + ( \int_compare_p:nNn \etex_lastnodetype:D = \c_twelve && + \g_xeCJK_itcorr_bool ) + } + { \CJKecglue } + { + \bool_if:nT + { + \l_xeCJK_xecglue_bool && + \int_compare_p:nNn \etex_lastnodetype:D = \c_eleven && + ( \int_compare_p:nNn + \tex_lastskip:D = { \tex_fontdimen:D \c_two \tex_font:D } || + \int_compare_p:nNn \tex_lastskip:D = \l_xeCJK_ecglue_dim ) + } + { + \skip_set_eq:NN \l_tmpa_skip \tex_lastskip:D + \tex_unskip:D + \bool_if:nTF + { + \int_compare_p:nNn \tex_lastkern:D = \c_four || + \int_compare_p:nNn \etex_lastnodetype:D = \c_ten || + \int_compare_p:nNn \tex_lastkern:D = \c_three || + \g_xeCJK_itcorr_bool + } + { \CJKecglue } + { + \bool_if:nT + { + ! ( \int_compare_p:nNn \tex_lastkern:D = \c_one ) || + ! ( \int_compare_p:nNn \tex_lastkern:D = \c_two ) || + \l_xeCJK_space_bool + } + { \skip_horizontal:N \l_tmpa_skip } + } + } + } + } + \bool_gset_false:N \g_xeCJK_itcorr_bool + } + \c_group_begin_token + \xeCJK_clear_CJK_toks: + \xeCJK_select_font: + \CJKsymbol + } +% \end{macrocode} +% \end{macro} % -% 需要指出,\xeCJK\ 包不需要 CJK 包的支持,并且 \xeCJK\ 包自动禁止载入 CJK 包。 +% \begin{macrocode} +\xeCJK_inter_class_toks:nnn { CJK } { Boundary } + { + \c_group_end_token + { \xeCJK_CJK_kern: } + \xeCJK_ignorespaces: + } +\xeCJK_inter_class_toks:nnn { CJK } { CJK } { \xeCJK_CJK_and_CJK:N } +% \end{macrocode} +% +% \begin{macro}[internal]{\xeCJK_CJK_and_CJK:N} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_CJK_and_CJK:N { \CJKglue \CJKsymbol {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\clist_map_inline:nn { FullLeft, FullRight } + { + \xeCJK_inter_class_toks:nnn { Boundary } {#1} + { + \c_group_begin_token + \xeCJK_clear_CJK_toks: + \xeCJK_select_font: + \use:c { xeCJK_CJK_and_#1:N } + } + \xeCJK_inter_class_toks:nnn {#1} { CJK } { \CJKsymbol } + \xeCJK_inter_class_toks:nnn {#1} { Boundary } + { \c_group_end_token \tex_ignorespaces:D } + \clist_map_inline:nn { CJK, Boundary } + { + \exp_args:Nnnx \xeCJK_pre_inter_class_toks:nnn {#1} {##1} + { + \str_if_eq:xxTF {#1} { FullLeft } + { \exp_not:N \nobreak } { \exp_not:N \xeCJK_after_FullRight: } + } + } + } +% \end{macrocode} % +% \begin{macro}[internal]{\xeCJK_punct_rule:n} +% 用于抹去标点符号的左/右空白。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_punct_rule:n + { + \tex_vrule:D + \@width \dim_eval:c { \l_xeCJK_punct_coor_tl/rule/#1 } + \@depth \c_zero_dim + \@height \c_zero_dim \scan_stop: + } +% \end{macrocode} +% \end{macro} % -% \title{ \hypertarget{English}{The xeCJK Package} -% \hbox to 0pt{\hskip 40mm\hyperlink{Chinese}{\normalsize 中文版}}\\[1ex] -% \normalsize Ver. \fileversion} -% \author{Wenchang Sun} -% \date{\filedate} -% \maketitle +% \begin{macro}[internal]{\xeCJK_punct_glue:n} +% 根据所选的标点处理方式在标点符号左/右增加的空白。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_punct_glue:n + { + \skip_horizontal:n + { + \dim_eval:c { \l_xeCJK_punct_coor_tl/glue/#1 } + \@plus \dim_eval:n { \tl_use:c { \l_xeCJK_punct_coor_tl/glue/#1 } /4 } + \@minus \dim_eval:n { \tl_use:c { \l_xeCJK_punct_coor_tl/glue/#1 } /2 } + } + } +% \end{macrocode} +% \end{macro} % -% \newpage +% \begin{macro}[internal]{\xeCJK_punct_kern:n} +% 相邻两个标点之间的间距。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_punct_kern:n + { \tex_kern:D \dim_eval:c { \l_xeCJK_punct_coor_tl/kern/#1 } } +% \end{macrocode} +% \end{macro} % -% \section{Main features} -% The package \xeCJK\ allows XeLaTeX users to typeset CJK scripts easily. +% \begin{macro}[internal]{\dim_eval:c} +% \begin{macrocode} +\cs_generate_variant:Nn \dim_eval:n { c } +% \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\xeCJK_before_FullLeft:N} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_before_FullLeft:N + { + \tl_set:Nx \l_xeCJK_lastpunct_tl {#1} + \xeCJK_punct_rule:n { l/#1 } + \CJKpunctsymbol {#1} + } +% \end{macrocode} +% \end{macro} % -% \begin{enumerate} -% \item different default fonts for CJK and other characters; -% \item spaces automatically ignored between CJK characters; -% \item special effects on full-width CJK punctuation; and -% \item automatic adjustment of the space between CJK and other characters. -% \end{enumerate} +% \begin{macro}[internal]{\xeCJK_after_FullRight:} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_after_FullRight: + { + \xeCJK_get_punct_bounds:nV { r } \l_xeCJK_lastpunct_tl + \xeCJK_punct_rule:n { r/\l_xeCJK_lastpunct_tl } + \xeCJK_punct_glue:n { r/\l_xeCJK_lastpunct_tl } + } +% \end{macrocode} +% \end{macro} % -% \section{Usage} -% -% To use \xeCJK, one need some version of XeTeX after [2008/03/07]. -% -% \begin{decl} -% \defmacro{\usepackage}[\textcolor{optioncolor}{Options}] -% \{\textcolor{parametercolor}{xeCJK}\} -% \end{decl} -% -% \def\arraystretch{1.5} -% \begin{tabular}{lp{90mm}} -% Options & \\ -% BoldFont: & Create "synthetic bold" fonts for CJK characters. -% Will be overridden by specifying {BoldFont} -% in the definition of a CJK family. -% \\ -% SlantFont: & Create slanted fonts for CJK characters. -% Will be overridden by specifying {ItalicFont} -% in the definition of a CJK family. -% \\ -% CJKnumber: & Load the CJKnumb package. -% \\ -% CJKchecksingle: & Prevent last line with only one CJK character\\ -% nospace: & Ignore spaces between CJK ideographs\\ -% space: & Do not ignore spaces between CJK ideographs\\ -% \end{tabular} +% \begin{macrocode} +\clist_map_inline:nn { CJK, FullLeft, FullRight } + { + \clist_map_inline:nn { FullLeft, FullRight } + { \xeCJK_inter_class_toks:nnc {#1} {##1} { xeCJK_#1_and_##1:N } } + } +% \end{macrocode} % +% \begin{macro}[internal]{\xeCJK_CJK_and_FullLeft:N} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_CJK_and_FullLeft:N + { + \xeCJK_get_punct_bounds:nN { l } {#1} + \int_compare:nNnF \etex_lastnodetype:D = \c_one + { \xeCJK_punct_glue:n { l/#1 } } + \xeCJK_before_FullLeft:N {#1} + \xeCJK_punct_if_middle:NT {#1} + { + \xeCJK_punct_rule:n { m/#1 } + \xeCJK_punct_glue:n { l/#1 } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_CJK_and_FullRight:N} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_CJK_and_FullRight:N + { + \xeCJK_get_punct_bounds:nN { r } {#1} + \xeCJK_punct_if_long:NTF {#1} \CJKglue + { + \nobreak + \xeCJK_punct_if_middle:NT {#1} + { + \xeCJK_punct_glue:n { r/#1 } + \xeCJK_punct_rule:n { m/#1 } + } + } + \tl_gset:Nx \l_xeCJK_lastpunct_tl {#1} + \CJKpunctsymbol {#1} + } +% \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\xeCJK_FullLeft_and_FullLeft:N} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_FullLeft_and_FullLeft:N + { + \nobreak + \xeCJK_get_punct_bounds:nN { l } {#1} + \xeCJK_get_kern:VN \l_xeCJK_lastpunct_tl {#1} + \xeCJK_punct_kern:n { \l_xeCJK_lastpunct_tl - #1 } + \xeCJK_before_FullLeft:N {#1} + } +% \end{macrocode} +% \end{macro} % -% \begin{decl} -% \defmacro{\setCJKmainfont} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKsansfont} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKmonofont} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKmonofont*} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKmonofont+} [\textcolor{optioncolor}{<font features>}]\arg{font name}\\ -% \defmacro{\setCJKfamilyfont} \arg{family name}[\textcolor{optioncolor} -% {<font features>}]\arg{font name}\\ -% \defmacro{\setCJKfallbackfamilyfont} \arg{family name} -% [\textcolor{optioncolor}{<font features>}]\arg{font name} -% \end{decl} -% -% The first three macros are analogs of -% \begin{quote} -% \defmacro{\setmainfont}, \defmacro{\setsansfont}, and \defmacro{\setmonofont}, -% \end{quote} -% respectively. -% The only difference is that they effect only CJK characters. -% -% The last two macros set the primary font and fallback font for a CJK family -% which will be called by -% \begin{quote} -% \defmacro{\CJKfamily}\arg{family name}. -% \end{quote} -% With these macros, one can set different default fonts for CJK and other characters, -% respectively. -% -% For a full description on the parameters \textcolor{optioncolor}{<font features>} -% and \arg{font name}, -% we refer to the package \verb+fontspec+. -% -% Threr are \defmacro{\CJKfamilydefault}, \defmacro{\CJKrmdefault}, -% \defmacro{\CJKsfdefault} and \defmacro{\CJKttdefault}, which correspond to -% \verb+\familydefault+, \verb+\rmdefault+, \verb+\sfdefault+ and -% \verb+\ttdefault+. For example, one can select sans serief CJK font for -% slides: -% \begin{verbatim} -% \renewcommand\CJKfamilydefault{\CJKsfdefault} -% \end{verbatim} -% -% \defmacro{\setCJKmonofont} can be appended with a |*| or |+| symbol. They make sure -% that the width of a CJK glyph equals to 2 space for monospace fonts, by scaling and -% spacing, respectively. -% -% \defmacro{\CJKfixedspacing} sets fixed CJK character spacing and |plain| -% punctuation style. \defmacro{\CJKflexiblespacing} restores flexible CJK -% character spacing and old punctuation style. |verbatim| environemnts sets -% |\CJKfixedspacing| automatically. -% -% \defmacro{\setCJKmonoscale} and \defmacro{\setCJKmonoexspace} reset the scale and extra -% space introduced by |\setCJKmainfont*| and |\setCJKmonofont+|, respectively. They are -% useful when changing the font size. -% -% \section{Advanced settings} -% -% -% -% \begin{decl} -% \defmacro{\punctstyle}\arg{punct style} -% \end{decl} -% -% Set the CJK punctuation style. \xeCJK\ predefines several styles for typesetting full-width punctuation. -% -% -% \begin{tabular}{lp{60mm}} -% style& \\ -% \textcolor{parametercolor}{quanjiao} or \textcolor{parametercolor}{fullwidth}& typeset all punctuation in full-width, -% for two adjoint punctuation, the first is typeset -% in half-width. -% \\ -% \textcolor{parametercolor}{banjiao} or \textcolor{parametercolor}{halfwidth}& typeset all punctuation in half-width. -% \\ -% \textcolor{parametercolor}{kaiming} or \textcolor{parametercolor}{mixedwidth}& typeset all punctuation in half-width except -% the period, question, and exclamation marks.\\ -% \textcolor{parametercolor}{hangmobanjiao} or \textcolor{parametercolor}{marginkerning} & typeset punctuation at the end of lines in half-width. -% \end{tabular} +% \begin{macro}[internal]{\xeCJK_FullLeft_and_FullRight:N} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_FullLeft_and_FullRight:N + { + \nobreak + \xeCJK_get_punct_bounds:nN { r } {#1} + \xeCJK_get_kern:VN \l_xeCJK_lastpunct_tl {#1} + \xeCJK_punct_kern:n { \l_xeCJK_lastpunct_tl - #1 } + \nobreak + \tl_set:Nx \l_xeCJK_lastpunct_tl {#1} + \CJKpunctsymbol {#1} + } +% \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\xeCJK_FullRight_and_FullLeft:N} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_FullRight_and_FullLeft:N + { + \xeCJK_punct_rule:n { r/\l_xeCJK_lastpunct_tl } + \xeCJK_get_punct_bounds:nN { l } {#1} + \xeCJK_get_kern:VN \l_xeCJK_lastpunct_tl {#1} + \xeCJK_punct_kern:n { \l_xeCJK_lastpunct_tl - #1 } + \xeCJK_punct_nobreak: + \xeCJK_before_FullLeft:N {#1} + } +% \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\xeCJK_FullRight_and_FullRight:N} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_FullRight_and_FullRight:N + { + \xeCJK_punct_rule:n { r/\l_xeCJK_lastpunct_tl } + \xeCJK_get_punct_bounds:nN { r } {#1} + \xeCJK_get_kern:VN \l_xeCJK_lastpunct_tl {#1} + \xeCJK_punct_kern:n { \l_xeCJK_lastpunct_tl - #1 } + \nobreak + \tl_set:Nx \l_xeCJK_lastpunct_tl {#1} + \CJKpunctsymbol {#1} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\xeCJK_CJK_kern:,\xeCJK_CJK_space_kern:, +% \xeCJK_default_kern:, \xeCJK_default_space_kern:} +% 用于判断插入的各种 |kern|。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_CJK_kern: { \tex_kern:D -1 sp \tex_kern:D 1 sp } +\cs_new_nopar:Nn \xeCJK_CJK_space_kern: { \tex_kern:D -2 sp \tex_kern:D 2 sp } +\cs_new_nopar:Nn \xeCJK_default_kern: { \tex_kern:D -3 sp \tex_kern:D 3 sp } +\cs_new_nopar:Nn \xeCJK_default_space_kern: { \tex_kern:D -4 sp \tex_kern:D 4 sp } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{CJKglue} +% CJK 文字之间插入的 |glue|。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } { CJKglue .tl_set_x:N = \CJKglue } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{CJKecglue,xCJKecglue} +% CJK 与西文和数学行内数学公式之间自动添加的空白。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { + CJKecglue .code:n = + { + \cs_set:Npx \CJKecglue {#1} + \settowidth \l_xeCJK_ecglue_dim \CJKecglue + }, + xCJKecglue .choice:, + xCJKecglue / true .code:n = + { + \bool_set_true:N \l_xeCJK_xecglue_bool + \cs_set_eq:NN \xeCJK_space_or_xecglue: \CJKecglue + }, + xCJKecglue / false .code:n = + { + \bool_set_false:N \l_xeCJK_xecglue_bool + \cs_set_eq:NN \xeCJK_space_or_xecglue: \c_space_token + }, + xCJKecglue / unknown .code:n = + { + \bool_set_true:N \l_xeCJK_xecglue_bool + \cs_set:Npx \CJKecglue {#1} + \settowidth \l_xeCJK_ecglue_dim \CJKecglue + \cs_set_eq:NN \xeCJK_space_or_xecglue: \CJKecglue + }, + xCJKecglue .default:n = { true } , + } +\dim_new:N \l_xeCJK_ecglue_dim +\bool_new:N \l_xeCJK_xecglue_bool +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{CJKspace} +% 是否保留 CJK 文字间的空白,默认不保留。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { + CJKspace .choice:, + CJKspace / true .code:n = { \CJKspace }, + CJKspace / false .code:n = { \CJKnospace }, + CJKspace .default:n = { true }, + space .meta:n = { CJKspace = true }, + nospace .meta:n = { CJKspace = false }, + } +% \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\CJKspace,\CJKnospace} +% 是否保留 CJK 文字间的空白,默认不保留。 +% \begin{macrocode} +\NewDocumentCommand \CJKspace { } + { + \bool_set_true:N \l_xeCJK_space_bool + \cs_set_eq:NN \xeCJK_ignorespaces: \xeCJK_peek_math: + } +\NewDocumentCommand \CJKnospace { } + { + \bool_set_false:N \l_xeCJK_space_bool + \cs_set_eq:NN \xeCJK_ignorespaces: \xeCJK_ignore_spaces: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_ignore_spaces:,\xeCJK_peek_math:} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_ignore_spaces: + { + \peek_catcode:NTF \c_space_token + { + \int_compare:nNnT \tex_lastkern:D = \c_one + { \tex_unkern:D \tex_unkern:D { \xeCJK_CJK_space_kern: } } + \peek_catcode_ignore_spaces:NTF \c_math_toggle_token + { \xeCJK_space_or_xecglue: } + { \bool_if:nT { \token_if_cs_p:N \l_peek_token } \xeCJK_space_or_xecglue: } + } + { + \token_if_math_toggle:NTF \l_peek_token \CJKecglue + { \cs_if_exist:NF \l_peek_token \exp_not:N } + } + } +\cs_new_nopar:Nn \xeCJK_peek_math: + { + \peek_catcode:NTF \c_space_token + { + \int_compare:nNnT \tex_lastkern:D = \c_one + { \tex_unkern:D \tex_unkern:D { \xeCJK_CJK_space_kern: } } + \peek_catcode_ignore_spaces:NF \c_space_token { \xeCJK_space_or_xecglue: } + } + { + \token_if_math_toggle:NTF \l_peek_token \CJKecglue + { \cs_if_exist:NF \l_peek_token \exp_not:N } + } + } +% \end{macrocode} +% \end{macro} % +% \subsection{段末孤字处理} % -% \begin{decl} -% \defmacro{\xeCJKallowbreakbetweenpuncts} \\ -% \defmacro{\xeCJKnobreakbetweenpuncts} -% \end{decl} +% \begin{macro}{CheckSingle} +% \begin{macro}[aux]{CheckSingleglue} +% 孤字处理功能选项。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { + CheckSingle .choice:, + CheckSingle / true .code:n = { \xeCJKenablechecksingle }, + CheckSingle / false .code:n = { \xeCJKdisablechecksingle }, + CheckSingle .default:n = { true }, + CJKchecksingle .meta:n = { CheckSingle = true } , + CheckSingleglue .tl_set_x:N = { \CJKchecksingleglue }, + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJKenablechecksingle,\xeCJKdisablechecksingle} +% 孤字处理功能开关。 +% \begin{macrocode} +\bool_new:N \l_xeCJK_checksingle_bool +\NewDocumentCommand \xeCJKenablechecksingle { } + { + \bool_if:NF \l_xeCJK_checksingle_bool + { + \bool_set_true:N \l_xeCJK_checksingle_bool + \cs_set_eq:NN \xeCJK_checksingle_save_CJKsymbol:N \xeCJK_CJK_and_CJK:N + \cs_set_eq:NN \xeCJK_checksingle_save_CJKglue \CJKglue + \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \xeCJK_checksingle:N + \cs_set_nopar:Npn \CJKglue { \CJKchecksingleglue } + } + } +\NewDocumentCommand \xeCJKdisablechecksingle { } + { + \bool_if:NT \l_xeCJK_checksingle_bool + { + \bool_set_false:N \l_xeCJK_checksingle_bool + \cs_set_eq:NN \CJKglue \xeCJK_checksingle_save_CJKglue + \cs_set_eq:NN \xeCJK_CJK_and_CJK:N \xeCJK_checksingle_save_CJKsymbol:N + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_checksingle:N,\xeCJK_checksingle:NN,\xeCJK_checksingle:NNN} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_checksingle:N + { + \peek_catcode:NTF \c_catcode_other_token + { \xeCJK_checksingle:NN {#1} } + { + \bool_if:nTF + { + \tl_if_empty_p:x { \token_get_arg_spec:N \l_peek_token } && + \exp_args:No \tl_if_single_token_p:n \l_peek_token && + \exp_after:wN \token_if_other_p:N \l_peek_token + } + { \xeCJK_checksingle:NN {#1} } + { \xeCJK_checksingle_save_CJKsymbol:N {#1} } + } + } +\cs_new_nopar:Nn \xeCJK_checksingle:NN + { + \peek_catcode:NTF \c_catcode_other_token + { \xeCJK_checksingle_save_CJKsymbol:N {#1} #2 } + { + \bool_if:nTF + { + \token_if_space_p:N \l_peek_token || + \token_if_math_toggle_p:N \l_peek_token || + \token_if_cs_p:N \l_peek_token + } + { + \bool_if:nTF { \token_if_space_p:N \l_peek_token } + { + \peek_catcode_ignore_spaces:NTF \c_catcode_other_token + { \xeCJK_checksingle_save_CJKsymbol:N {#1} #2 \c_space_token } + { + \bool_if:nTF + { + \token_if_math_toggle_p:N \l_peek_token || + \token_if_cs_p:N \l_peek_token + } + { \xeCJK_checksingle:NNN {#1} {#2} \c_space_token } + { \xeCJK_checksingle_save_CJKsymbol:N {#1} #2 \c_space_token } + } + } + { \xeCJK_checksingle:NNN {#1} {#2} { } } + } + { \xeCJK_checksingle_save_CJKsymbol:N {#1} #2 } + } + } +\cs_new_nopar:Nn \xeCJK_checksingle:NNN + { + \bool_if:nTF + { + \token_if_eq_meaning_p:NN \l_peek_token \par || + \token_if_eq_meaning_p:NN \l_peek_token \[ % \] + } + { \CJKsymbol {#1} \nobreak #2 } + { \xeCJK_checksingle_env:NNN {#1} {#2} {#3} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_checksingle_env:NNN,\xeCJK_checksingle_env:NNNNn} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_checksingle_env:NNN + { + \peek_catcode_remove:NTF \c_math_toggle_token + { + \peek_catcode:NTF \c_math_toggle_token + { \CJKsymbol {#1} \nobreak #2 \c_math_toggle_token } + { \xeCJK_checksingle_save_CJKsymbol:N {#1} #2#3 \c_math_toggle_token } + } + { + \peek_meaning_remove:NTF \begin + { \xeCJK_checksingle_env:NNNNn {#1} {#2} {#3} \begin } + { + \peek_meaning_remove:NTF \end + { \xeCJK_checksingle_env:NNNNn {#1} {#2} {#3} \end } + { \xeCJK_checksingle_save_CJKsymbol:N {#1} #2#3 } + } + } + } +\cs_new_nopar:Nn \xeCJK_checksingle_env:NNNNn + { + \clist_if_in:NnTF \g_xeCJK_inline_env_clist {#5} + { \xeCJK_checksingle_save_CJKsymbol:N {#1} #2#3 } + { \CJKsymbol {#1} \nobreak #2 } + \scan_stop: #4 {#5} + } +% \end{macrocode} +% \end{macro} % -% By default, \xeCJK\ prohibits line breaks between punctuation. Use +% \begin{macro}[internal,var]{\g_xeCJK_inline_env_clist} +% \begin{macrocode} +\clist_new:N \g_xeCJK_inline_env_clist +% \end{macrocode} +% \end{macro} % -% \defmacro{\xeCJKallowbreakbetweenpuncts}\newline -% to make it breakable. +% \begin{macro}{InlineEnv,InlineEnv+,InlineEnv-} +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { + InlineEnv .clist_gset:N = \g_xeCJK_inline_env_clist , + InlineEnv+ .code:n = + { + \clist_gput_right:Nx \g_xeCJK_inline_env_clist {#1} + \clist_gremove_duplicates:N \g_xeCJK_inline_env_clist + }, + InlineEnv- .code:n = + { + \clist_map_inline:xn {#1} + { \clist_gremove_all:Nn \g_xeCJK_inline_env_clist {##1} } + }, + } +% \end{macrocode} +% \end{macro} % +% \subsection{增加 CJK 子分区} % -% \begin{decl} -% \defmacro{\xeCJKsetslantfactor}\arg{slant factor}\\ -% \defmacro{\xeCJKsetemboldenfactor}\arg{embolden factor} -% \end{decl} -% Set slant and embolden factors, respectively. The default settings are -% \begin{verbatim} -% \xeCJKsetslantfactor{0.17} -% \xeCJKsetemboldenfactor{4} -% \end{verbatim} +% \begin{macro}[internal]{\xeCJK_UL_subclass_patch_tl,\g_xeCJK_CJK_subclass_clist} +% \begin{macrocode} +\tl_new:N \xeCJK_UL_subclass_patch_tl +\clist_new:N \g_xeCJK_CJK_subclass_clist +% \end{macrocode} +% \end{macro} % -% Note that both macros effect only CJK families defined after them. +% \begin{macro}[internal]{\xeCJK_erase_CJKsymbol:, \xeCJK_restore_CJKsymbol:} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_erase_CJKsymbol: + { + \cs_gset_eq:NN \CJKsymbol_Block \CJKsymbol + \cs_gset_eq:NN \CJKsymbol \prg_do_nothing: + } +\cs_new_nopar:Nn \xeCJK_restore_CJKsymbol: + { + \cs_gset_eq:NN \CJKsymbol \CJKsymbol_Block + \CJKsymbol + } +% \end{macrocode} +% \end{macro} % +% \begin{macro}{\xeCJKDeclareSubCJKBlock} +% 声明 CJK 子区范围,|#1| 为自定义名称,|#2| 为子区的 |Unicode| 范围。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKDeclareSubCJKBlock { m m } + { \xeCJKDeclareSubCharClass { CJK } {#1} {#2} } +\@onlypreamble \xeCJKDeclareSubCJKBlock +% \end{macrocode} +% \end{macro} % -% \begin{decl} -% \defmacro{\CJKnospace}\\ -% \defmacro{\CJKspace} -% \end{decl} -% \verb+\CJKnospace+ ignores spaces between CJK ideographs, see also -% \verb+nospace+ option. \verb+\CJKspace+ reserves the spaces. +% \begin{macro}{\xeCJKCancelSubCJKBlock,\xeCJKRestoreSubCJKBlock} +% 取消和恢复对 CJK 子区的声明。 +% \begin{macrocode} +\bool_new:N \l_xeCJK_sub_cancel_bool +\NewDocumentCommand \xeCJKCancelSubCJKBlock { m } + { + \bool_if:NF \l_xeCJK_sub_cancel_bool + { + \bool_set_true:N \l_xeCJK_sub_cancel_bool + \xeCJK_sub_restore_or_cancel:n {#1} + } + } +\NewDocumentCommand \xeCJKRestoreSubCJKBlock { m } + { + \bool_if:NT \l_xeCJK_sub_cancel_bool + { + \bool_set_false:N \l_xeCJK_sub_cancel_bool + \xeCJK_sub_restore_or_cancel:n {#1} + } + } +\cs_new_nopar:Nn \xeCJK_sub_restore_or_cancel:n + { + \clist_map_inline:xn {#1} + { + \cs_if_free:cTF { xeCJK_ CJK/##1 _class } + { \xeCJK_error:nx { SubBlock-undefined } {##1} } + { + \xeCJKDeclareCharClass + { CJK \bool_if:NF \l_xeCJK_sub_cancel_bool { /##1 } } + { \clist_use:c { g_xeCJK_CJK/##1_range_clist } } + } + } + } +\xeCJK_msg_new:nn { SubBlock-undefined } + { + The~CJK~sub~block~'#1'~is~undefined.\\\\ + Try~to~use~\token_to_str:N \xeCJKDeclareSubCJKBlock \c_space_tl + to~declare~it. + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJKDeclareSubCharClass} +% \begin{macrocode} +\NewDocumentCommand \xeCJKDeclareSubCharClass + { > { \TrimSpaces } m > { \TrimSpaces } m m } + { + \cs_if_free:cT { xeCJK_ #1/#2 _class } + { + \xeCJK_new_class:n { #1/#2 } + \xeCJK_set_sub_class_toks:nn {#1} {#2} + \xeCJK_new_sub_key:n {#2} + \xeCJK_UL_subclass_patch:nn {#1} {#2} + } + \xeCJKDeclareCharClass { #1/#2 } {#3} + } +\@onlypreamble \xeCJKDeclareSubCharClass +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_set_sub_class_toks:nn} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_set_sub_class_toks:nn + { + \clist_map_inline:Nn \g_xeCJK_base_class_clist + { + \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } {##1} {#1} {##1} + \xeCJK_copy_inter_class_toks:nnnn {##1} { #1/#2 } {##1} {#1} + \str_if_eq:xxTF {##1} { CJK } + { + \xeCJK_pre_inter_class_toks:nnn {##1} { #1/#2 } + { \xeCJK_switch_font:nn {#1} {#2} } + } + { + \xeCJK_pre_inter_class_toks:nnn {##1} { #1/#2 } + { \xeCJK_erase_CJKsymbol: } + \xeCJK_app_inter_class_toks:nnn {##1} { #1/#2 } + { \xeCJK_switch_font:nn {#1} {#2} \xeCJK_restore_CJKsymbol: } + } + } + \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/#2 } {#1} {#1} + \clist_if_empty:NF \g_xeCJK_CJK_subclass_clist + { + \clist_map_inline:Nn \g_xeCJK_CJK_subclass_clist + { + \xeCJK_copy_inter_class_toks:nnnn { #1/#2 } { #1/##1 } {#1} {#1} + \xeCJK_copy_inter_class_toks:nnnn { #1/##1 } { #1/#2 } {#1} {#1} + \xeCJK_pre_inter_class_toks:nnn { #1/#2 } { #1/##1 } + { \xeCJK_switch_font:nn {#2} {##1} } + \xeCJK_pre_inter_class_toks:nnn { #1/##1 } { #1/#2 } + { \xeCJK_switch_font:nn {##1} {#2} } + } + } + \clist_gput_right:Nn \g_xeCJK_CJK_subclass_clist {#2} + \xeCJK_save_CJK_class:n { #1/#2 } + \clist_map_inline:nn { CJK, FullLeft, FullRight } + { + \xeCJK_pre_inter_class_toks:nnn { #1/#2 } {##1} + { \xeCJK_switch_font:nn {#2} {#1} } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_UL_subclass_patch:nn} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_UL_subclass_patch:nn + { + \tl_put_right:Nn \xeCJK_UL_subclass_patch_tl + { + \clist_map_inline:nn { Default, HalfLeft, HalfRight } + { + \str_if_eq:xxTF {##1} { HalfLeft } + { \xeCJK_inter_class_toks:nnn {#1} { #1/#2 } { \CJKecglue \CJKsymbol } } + { \xeCJK_inter_class_toks:nnn {#1} { #1/#2 } { \CJKsymbol } } + \xeCJK_inter_class_toks:nnn { Boundary } { #1/#2 } + { + \xeCJK_erase_CJKsymbol: + \xeCJK_Boundary_and_CJK: + \xeCJK_switch_font:nn {#1} {#2} + \xeCJK_restore_CJKsymbol: + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{标点处理} +% +% \begin{macro}[internal,var]{\g_xeCJK_punctstyle_clist} +% 标点处理方式。 +% \begin{macrocode} +\clist_new:N \g_xeCJK_punctstyle_clist +\clist_set:Nn \g_xeCJK_punctstyle_clist + { CCT , halfwidth , fullwidth , marginkerning , mixedwidth , plain } +\clist_map_inline:Nn \g_xeCJK_punctstyle_clist + { \tl_const:cn { c_xeCJK_ps_#1_tl } {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\keys_choices_generate:V, .generate_choices:V} +% \begin{macrocode} +\cs_generate_variant:Nn \keys_choices_generate:n { V } +\cs_new_protected:cpn { \c_keys_props_root_tl .generate_choices:V } #1 + { \keys_choices_generate:V {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% {PunctStyle, AllowBreakBetweenPuncts, KaiMingPunct, +% LongPunct, MiddlePunct,PunctWidth} +% 相关选项声明。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { + AllowBreakBetweenPuncts .choice:, + AllowBreakBetweenPuncts / true .code:n = { \xeCJKallowbreakbetweenpuncts }, + AllowBreakBetweenPuncts / false .code:n = { \xeCJKnobreakbetweenpuncts }, + AllowBreakBetweenPuncts .default:n = { true }, + KaiMingPunct .code:n = { \xeCJK_set_special_punct:nn { mixedwidth } {#1} }, + KaiMingPunct+ .code:n = { \xeCJK_add_special_punct:nn { mixedwidth } {#1} }, + KaiMingPunct- .code:n = { \xeCJK_sub_special_punct:nn { mixedwidth } {#1} }, + LongPunct .code:n = { \xeCJK_set_special_punct:nn { long } {#1} }, + LongPunct+ .code:n = { \xeCJK_add_special_punct:nn { long } {#1} }, + LongPunct- .code:n = { \xeCJK_sub_special_punct:nn { long } {#1} }, + MiddlePunct+ .code:n = { \xeCJK_add_special_punct:nn { middle } {#1} }, + MiddlePunct .code:n = { \xeCJK_set_special_punct:nn { middle } {#1} }, + MiddlePunct- .code:n = { \xeCJK_sub_special_punct:nn { middle } {#1} }, + PunctWidth .tl_gset:N = \g_xeCJK_punct_width_tl , + PunctStyle .choice_code:n = + { + \tl_set:Nx \l_xeCJK_punctstyle_tl { \l_keys_choice_tl } + \tl_if_eq:NNT \l_xeCJK_punctstyle_tl \c_xeCJK_ps_plain_tl + { \xeCJKallowbreakbetweenpuncts } + }, + PunctStyle .generate_choices:V = \g_xeCJK_punctstyle_clist, + PunctStyle / banjiao .meta:n = { PunctStyle = halfwidth }, + PunctStyle / quanjiao .meta:n = { PunctStyle = fullwidth }, + PunctStyle / kaiming .meta:n = { PunctStyle = mixedwidth }, + PunctStyle / hangmobanjiao .meta:n = { PunctStyle = marginkerning }, + PunctStyle / unknown .code:n = + { \xeCJK_error:nx { PunctStyle-undefined } \l_keys_value_tl }, + } +\xeCJK_msg_new:nn { PunctStyle-undefined } + { + Punctstyle~"#1"~is~not~available. \\\\ + You~can~only~use~one~of\\\\ + "\g_xeCJK_punctstyle_clist".\\ + } +% \end{macrocode} +% \end{macro} % +% \begin{macro}[internal]{\xeCJKallowbreakbetweenpuncts, \xeCJKnobreakbetweenpuncts} +% \begin{macrocode} +\NewDocumentCommand \xeCJKallowbreakbetweenpuncts { } + { \cs_set_eq:NN \xeCJK_punct_nobreak: \xeCJK_zero_glue: } +\NewDocumentCommand \xeCJKnobreakbetweenpuncts { } + { \cs_set_eq:NN \xeCJK_punct_nobreak: \nobreak } +\cs_new_protected_nopar:Nn \xeCJK_zero_glue: { \skip_horizontal:N \c_zero_skip } +% \end{macrocode} +% \end{macro} % -% \begin{decl} -% \defmacro{\xeCJKenablefallback}\\ -% \defmacro{\xeCJKdisablefallback} -% \end{decl} -% Enable or disable fallback fonts for CJK families. +% \begin{macro}[internal] +% {\g_xeCJK_special_ps_clist, \xeCJK_set_special_punct:nn, +% \xeCJK_add_special_punct:nn, \xeCJK_sub_special_punct:nn} +% \begin{macrocode} +\clist_set:Nn \g_xeCJK_special_ps_clist { mixedwidth , long , middle } +\clist_map_inline:Nn \g_xeCJK_special_ps_clist + { + \tl_new:c { l_xeCJK_#1_punct_tl } + \prop_new:c { l_xeCJK_#1_punct_prop } + } +\cs_new_nopar:Nn \xeCJK_set_special_punct:nn + { + \tl_set:cx { l_xeCJK_#1_punct_tl } {#2} + \prop_clear:c { l_xeCJK_#1_punct_prop } + \tl_map_inline:cn { l_xeCJK_#1_punct_tl } + { \prop_put:cnn { l_xeCJK_#1_punct_prop } {##1} { } } + } +\cs_new_nopar:Nn \xeCJK_add_special_punct:nn + { + \tl_put_right:cx { l_xeCJK_#1_punct_tl } {#2} + \tl_map_inline:cn { l_xeCJK_#1_punct_tl } + { \prop_put:cnn { l_xeCJK_#1_punct_prop } {##1} { } } + } +\cs_new_nopar:Nn \xeCJK_sub_special_punct:nn + { + \tl_map_inline:xn {#2} + { + \tl_remove_all:cn { l_xeCJK_#1_punct_tl } {##1} + \prop_del:cn { l_xeCJK_#1_punct_prop } {##1} + } + } +\cs_generate_variant:Nn \tl_map_inline:nn { x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\dim_set:Nc,\dim_add:Nc,\dim_set_min:Nc} +% \begin{macrocode} +\cs_generate_variant:Nn \dim_set:Nn { Nc } +\cs_generate_variant:Nn \dim_add:Nn { Nc } +\cs_generate_variant:Nn \dim_set_min:Nn { Nc } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal,var]{\l_xeCJK_punct_coor_tl} +% 记录当前字体状态下的标点处理方式。 +% \begin{macrocode} +\tl_set:Nn \l_xeCJK_punct_coor_tl { \l_xeCJK_font_coor_tl/\l_xeCJK_punctstyle_tl } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_get_punct_bounds:nN} +% |#1| 为 |l/r|,|#2| 为标点字符,返回标点的实际左/右空白的负值和根据标点处理方式 +% 决定添加的左/右空白。全角方式直接添加标点的实际左/右空白;半角方式添加标点左右空白 +% 中的最小值;开明方式与半角相同,只在开明标点再增加实际左/右空白的一半。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_get_punct_bounds:nN + { + \tl_if_exist:cF { \l_xeCJK_punct_coor_tl/rule/#1/#2 } + { + \tl_if_eq:NNTF \l_xeCJK_punctstyle_tl \c_xeCJK_ps_plain_tl + { + \clist_map_inline:nn { glue , rule , bound } + { \tl_gset:cV { \l_xeCJK_punct_coor_tl/##1/#1/#2 } \c_zero_dim } + \tl_gset:cV { \l_xeCJK_punct_coor_tl/rule/m/#2 } \c_zero_dim + } + { + \tl_if_exist:cF { \l_xeCJK_punct_coor_tl/bound/#1/#2 } + { { \xeCJK_select_font: \xeCJK_get_punct_dimen:N {#2} } } + \xeCJK_punct_if_long:NTF {#2} + { + \dim_zero:N \l_tmpa_dim + \dim_zero:N \l_tmpb_dim + \dim_zero:N \l_tmpc_dim + } + { + \dim_set:Nc \l_tmpa_dim { \l_xeCJK_punct_coor_tl/bound/#1/#2 } + \dim_set:Nc \l_tmpb_dim + { \l_xeCJK_punct_coor_tl/bound/\str_if_eq:xxTF {#1} lrl/#2 } + \dim_set:Nn \l_tmpc_dim + { + \tl_if_exist:cTF { g_xeCJK_punct_width/#2 } + { \tl_use:c { g_xeCJK_punct_width/#2 } } + { + \tl_if_blank:xTF \g_xeCJK_punct_width_tl + { \c_zero_dim } + { \g_xeCJK_punct_width_tl } + } + } + \xeCJK_punct_if_middle:NTF {#2} + { + \dim_set:Nn \l_tmpc_dim + { + \dim_compare:nNnTF \l_tmpc_dim > \c_zero_dim + { \l_tmpc_dim } + { + \prg_case_tl:Nnn \l_xeCJK_punctstyle_tl + { + \c_xeCJK_ps_halfwidth_tl { .5 em } + \c_xeCJK_ps_mixedwidth_tl { .5 em } + \c_xeCJK_ps_CCT_tl { .7 em } + \c_xeCJK_ps_fullwidth_tl { 1 em } + } + { 1 em } + } + - \tl_use:c { \l_xeCJK_punct_coor_tl/dimen/#2 } + } + \dim_set:Nn \l_tmpc_dim { .5 \l_tmpc_dim } + } + { + \dim_compare:nNnTF \l_tmpc_dim > \c_zero_dim + { + \dim_set:Nn \l_tmpc_dim + { + \l_tmpc_dim - \l_tmpb_dim + - \tl_use:c { \l_xeCJK_punct_coor_tl/dimen/#2 } + } + } + { + \dim_set_eq:NN \l_tmpc_dim \l_tmpa_dim + \dim_set_min:Nn \l_tmpc_dim \l_tmpb_dim + \prg_case_tl:Nnn \l_xeCJK_punctstyle_tl + { + \c_xeCJK_ps_halfwidth_tl { \prg_do_nothing: } + \c_xeCJK_ps_mixedwidth_tl + { + \xeCJK_punct_if_mixedwidth:NT {#2} + { + \dim_add:Nn \l_tmpc_dim { .5 \l_tmpa_dim } + \dim_set_min:Nn \l_tmpc_dim \l_tmpa_dim + } + } + \c_xeCJK_ps_CCT_tl + { + \xeCJK_punct_if_mixedwidth:NTF {#2} + { \dim_add:Nn \l_tmpc_dim { .5 \l_tmpa_dim } } + { \dim_add:Nn \l_tmpc_dim { .3 \l_tmpa_dim } } + \dim_set_min:Nn \l_tmpc_dim \l_tmpa_dim + } + } + { \dim_set_eq:NN \l_tmpc_dim \l_tmpa_dim } + } + } + \dim_set_max:Nn \l_tmpc_dim \c_zero_dim + } + \tl_gset:cx { \l_xeCJK_punct_coor_tl/rule/#1/#2 } + { - \dim_use:N \l_tmpa_dim } + \tl_gset:cx { \l_xeCJK_punct_coor_tl/rule/m/#2 } + { - \dim_use:N \l_tmpb_dim } + \tl_gset:cV { \l_xeCJK_punct_coor_tl/glue/#1/#2 } \l_tmpc_dim + } + } + } +\cs_generate_variant:Nn \xeCJK_get_punct_bounds:nN { nV } +% \end{macrocode} +% \end{macro} % +% \begin{macro}{\xeCJKsetwidth} +% \begin{macrocode} +\NewDocumentCommand \xeCJKsetwidth { m m } + { \tl_map_inline:xn {#1} { \tl_gset:cn { g_xeCJK_punct_width/##1 } {#2} } } +% \end{macrocode} +% \end{macro} % -% \section{Compatibility} +% \begin{macro}[pTF,internal] +% {\xeCJK_punct_if_right:N,\xeCJK_punct_if_both_left_right:NN, +% \xeCJK_punct_if_long:N,\xeCJK_punct_if_middle:N, +% \xeCJK_punct_if_mixedwidth:N} +% \begin{macrocode} +\prg_new_conditional:Nnn \xeCJK_punct_if_right:N { p , T , F , TF } + { + \tl_if_exist:cTF { \l_xeCJK_punct_coor_tl/glue/r/#1 } + \prg_return_true: \prg_return_false: + } +\prg_new_conditional:Nnn \xeCJK_punct_if_both_left_right:NN { p , T , F , TF } + { + \bool_if:nTF + { + ( \tl_if_exist_p:c { \l_xeCJK_punct_coor_tl/glue/r/#1 } && + \tl_if_exist_p:c { \l_xeCJK_punct_coor_tl/glue/r/#2 } ) || + ( \tl_if_exist_p:c { \l_xeCJK_punct_coor_tl/glue/l/#1 } && + \tl_if_exist_p:c { \l_xeCJK_punct_coor_tl/glue/l/#2 } ) + } + \prg_return_true: \prg_return_false: + } +\cs_generate_variant:Nn \prg_new_conditional:Nnn { c } +\clist_map_inline:Nn \g_xeCJK_special_ps_clist + { + \prg_new_conditional:cnn { xeCJK_punct_if_#1:N } { p , T , F , TF } + { + \prop_if_in:cnTF { l_xeCJK_#1_punct_prop } {##1} + \prg_return_true: \prg_return_false: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_get_kern:NN,\xeCJK_calc_kern:NN} +% 标点挤压。行末半角方式,相邻标点不挤压;全角方式,相邻两个标点占 1.5 汉字宽度, +% 半角、开明和 CCT 方式相邻标点占一个汉字宽度。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_get_kern:NN + { + \tl_if_exist:cF { \l_xeCJK_punct_coor_tl/kern/#1-#2 } + { + \dim_zero:N \l_tmpa_dim + \tl_if_eq:NNF \l_xeCJK_punctstyle_tl \c_xeCJK_ps_plain_tl + { + \tl_if_exist:cTF { g_xeCJK_punct/kern/#1-#2 } + { \dim_set:Nc \l_tmpa_dim { g_xeCJK_punct/kern/#1-#2 } } + { \xeCJK_calc_kern:NN {#1} {#2} } + } + \tl_gset:cV { \l_xeCJK_punct_coor_tl/kern/#1-#2 } \l_tmpa_dim + } + } +\cs_new_nopar:Nn \xeCJK_calc_kern:NN + { + \tl_if_eq:NNTF \l_xeCJK_punctstyle_tl \c_xeCJK_ps_marginkerning_tl + { + \xeCJK_punct_if_right:NT {#1} + { \dim_add:Nc \l_tmpa_dim { \l_xeCJK_punct_coor_tl/bound/r/#1 } } + \xeCJK_punct_if_right:NF {#2} + { \dim_add:Nc \l_tmpa_dim { \l_xeCJK_punct_coor_tl/bound/l/#2 } } + } + { + \tl_if_eq:NNTF \l_xeCJK_punctstyle_tl \c_xeCJK_ps_fullwidth_tl + { \xeCJK_calc_kern:NnNN \l_tmpa_dim { 1.5 em } {#1} {#2} } + { + \xeCJK_punct_if_both_left_right:NNTF {#1} {#2} + { + \xeCJK_punct_if_mixedwidth:NT {#1} + { + \xeCJK_calc_kern:NnNN \l_tmpa_dim { 1 em } {#1} {#2} + \dim_compare:nNnT \l_tmpa_dim < { .1 em } + { \dim_set:Nc \l_tmpa_dim { \l_xeCJK_punct_coor_tl/bound/l/#1 } } + } + } + { + \bool_if:nTF + { + \xeCJK_punct_if_mixedwidth_p:N {#1} && + ! ( \tl_if_eq_p:NN \l_xeCJK_punctstyle_tl \c_xeCJK_ps_halfwidth_tl ) + } + { + \dim_set:Nc \l_tmpa_dim { \l_xeCJK_punct_coor_tl/glue/r/#1 } + \dim_set:Nn \l_tmpa_dim { .7 \l_tmpa_dim } + } + { + \xeCJK_calc_kern:NnNN \l_tmpa_dim { 1 em } {#1} {#2} + \dim_compare:nNnT \l_tmpa_dim < { .1 em } + { + \dim_set:Nc \l_tmpa_dim { \l_xeCJK_punct_coor_tl/bound/l/#1 } + \dim_set_min:Nc \l_tmpa_dim { \l_xeCJK_punct_coor_tl/bound/r/#1 } + \dim_set:Nc \l_tmpb_dim { \l_xeCJK_punct_coor_tl/bound/l/#2 } + \dim_set_min:Nc \l_tmpb_dim { \l_xeCJK_punct_coor_tl/bound/r/#2 } + \dim_set_max:Nn \l_tmpa_dim \l_tmpb_dim + } + } + } + } + \bool_if:nT + { \xeCJK_punct_if_long_p:N {#1} || \xeCJK_punct_if_long_p:N {#2} } + { \dim_set_max:Nn \l_tmpa_dim { .1 em } } + } + \dim_set_max:Nn \l_tmpa_dim \c_zero_dim + } +\cs_generate_variant:Nn \xeCJK_get_kern:NN { V } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_calc_kern:NnNN} +% |#3| 和 |#4| 为相邻的两个标点,|#2| 为要确定的相邻两个标点总共占的宽度,|#1| 是 +% 尺寸寄存器,用于记录根据所占宽度计算得出的相邻两个标点间距。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_calc_kern:NnNN + { + \dim_set:Nn #1 + { + #2 + - \tl_use:c { \l_xeCJK_punct_coor_tl/ + \xeCJK_punct_if_right:NTF {#3} { bound } { glue } /l/#3 } + - \tl_use:c { \l_xeCJK_punct_coor_tl/ + \xeCJK_punct_if_right:NTF {#4} { glue } { bound } /r/#4 } + - \tl_use:c { \l_xeCJK_punct_coor_tl/dimen/#3 } + - \tl_use:c { \l_xeCJK_punct_coor_tl/dimen/#4 } + \xeCJK_punct_if_both_left_right:NNT {#3} {#4} + { + \tl_use:c { \l_xeCJK_punct_coor_tl/rule/m/#4 } } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_get_punct_dimen:N} +% 返回标点的左右空白和实际尺寸。对于破折号,计算两标点之间的空白,保证它中间不被断开。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_get_punct_dimen:N + { + \xeCJK_get_glyph_bounds:nNN { left } {#1} \l_tmpa_dim + \tl_gset:cV { \l_xeCJK_punct_coor_tl/bound/l/#1 } \l_tmpa_dim + \dim_set_eq:NN \l_tmpb_dim \l_tmpa_dim + \xeCJK_get_glyph_bounds:nNN { right } {#1} \l_tmpa_dim + \tl_gset:cV { \l_xeCJK_punct_coor_tl/bound/r/#1 } \l_tmpa_dim + \dim_add:Nn \l_tmpb_dim \l_tmpa_dim + \tl_gset:cx { \l_xeCJK_punct_coor_tl/dimen/#1 } + { \dim_eval:n { \etex_fontcharwd:D \tex_font:D `#1 - \l_tmpb_dim } } + \bool_if:nT + { + \xeCJK_punct_if_long_p:N {#1} && + ! ( \str_if_eq_p:xx {#1} { … } || \str_if_eq_p:xx {#1} { ‥ } ) + } + { + \clist_map_inline:Nn \g_xeCJK_punctstyle_clist + { + \str_if_eq:xxF \c_xeCJK_ps_plain_tl {##1} + { + \tl_gset:cx { \l_xeCJK_font_coor_tl/##1/kern/#1-#1 } + { - \dim_use:N \l_tmpb_dim } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_get_glyph_bounds:nNN} +% 用 |\XeTeXglyphbounds| 计算标点的上下左右空白。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_get_glyph_bounds:nNN + { + \dim_set:Nn #3 + { + \XeTeXglyphbounds + \prg_case_str:xxn {#1} + { + { left } { \c_one } { top } { \c_two } + { right } { \c_three } { bottom } { \c_four } + } + { \c_three } + \int_eval:n { \XeTeXcharglyph `#2 } + } + } +% \end{macrocode} +% \end{macro} % -% \subsection{CJK} -% To be compatible with some CJK-related packages \texttt{CJKnumb} -% and \texttt{CJKulem}, \xeCJK\ re-defines some macros in the package \texttt{CJK} -% and it is not compatible with the later. -% In fact, \xeCJK\ prevents automatically from loading \texttt{CJK} after \xeCJK. -% \StopEventually{} +% \begin{macro}{\xeCJKsetkern} +% 手动设置相邻标点的距离,仅在当前字体状态下有效。 +% \begin{macrocode} +\NewDocumentCommand \xeCJKsetkern { m m m } + { \tl_gset:cn { g_xeCJK_punct/kern/#1-#2 } {#3} } +% \end{macrocode} +% \end{macro} % -% \clearpage -% \part{xeCJK.sty} -% \section{宏包选项与内部工具} +% \subsection{后备字体} % -% \iffalse -%<*xeCJK> -% \fi -% \fontsize{10pt}{10pt}\selectfont -% \xeCJK\ 只能在XeLaTeX中使用 +% \begin{macro}{AutoFallBack} +% 后备字体的宏包选项声明。 % \begin{macrocode} -\RequirePackage{ifxetex} -\RequireXeTeX +\keys_define:nn { xeCJK / options } + { + AutoFallBack .choice:, + AutoFallBack / true .code:n = { \xeCJKenablefallback }, + AutoFallBack / false .code:n = { \xeCJKdisablefallback }, + AutoFallBack .default:n = { true }, + fallback .meta:n = { AutoFallBack = true }, + } % \end{macrocode} -% 禁止在\xeCJK\ 之后调入CJK包。 +% \end{macro} +% +% \begin{macro}[internal]{\xeCJKenablefallback, \xeCJKdisablefallback} +% 后备字体的启用开关,默认关闭。 % \begin{macrocode} -\expandafter\def\csname ver@CJK.sty\endcsname{2020/01/01} - -\newif\ifxeCJK@SlantFont@ - -\newif\ifxeCJK@BoldFont@ - -\newif\ifxeCJK@fallback@ - -\newif\ifxeCJK@num - -\newif\ifxeCJK@checksingle - -\newif\ifxeCJK@indentfirst -\xeCJK@indentfirsttrue - -\newif\ifxeCJK@space@ -\xeCJK@space@false - -\DeclareOption{boldfont}{\xeCJK@BoldFont@true} -\DeclareOption{BoldFont}{\ExecuteOptions{boldfont}} -\DeclareOption{slantfont}{\xeCJK@SlantFont@true} -\DeclareOption{SlantFont}{\ExecuteOptions{slantfont}} -\DeclareOption{fallback}{\xeCJK@fallback@true} -\DeclareOption{CJKnumber}{\xeCJK@numtrue} -\DeclareOption{normalindentfirst}{\xeCJK@indentfirstfalse} -\DeclareOption{CJKchecksingle}{\AtEndOfPackage{\let\xeCJK@i@i\xeCJK@checksingle}} -\DeclareOption{space}{\xeCJK@space@true} -\DeclareOption{nospace}{\xeCJK@space@false} - -\DeclareOption{CJKnormalspaces}{\PackageWarning{xeCJK}{% - obsolete option 'CJKnormalspaces'. It may be removed in the future.}} -\DeclareOption{CJKaddspaces}{\PackageWarning{xeCJK}{% - obsolete option 'CJKaddspaces'. It may be removed in the future.}} -\DeclareOption{CJKtextspaces}{\PackageWarning{xeCJK}{% - obsolete option 'CJKtextspaces'. It may be removed in the future.}} -\DeclareOption{CJKmathspaces}{\PackageWarning{xeCJK}{% - obsolete option 'CJKmathspaces'. It may be removed in the future.}} -\DeclareOption{CJKsetspaces}{\PackageWarning{xeCJK}{% - obsolete option 'CJKsetspaces'. It may be removed in the future.}} -\DeclareOption{CJKnospaces}{\PackageWarning{xeCJK}{% - obsolete option 'CJKnospaces'. It may be removed in the future.}} - -\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{fontspec}} -\ProcessOptions\relax - -\RequirePackage{xkeyval} -\RequirePackage{expl3} -\RequirePackage{fontspec} - -\ifxeCJK@indentfirst - \let\@afterindentfalse\relax -\fi +\bool_new:N \l_xeCJK_fallback_bool +\NewDocumentCommand \xeCJKenablefallback { } + { + \bool_if:NF \l_xeCJK_fallback_bool + { + \bool_set_true:N \l_xeCJK_fallback_bool + \cs_set_eq:NN \xeCJK_fallback_save_CJKsymbol:N \CJKsymbol + \cs_set_eq:NN \CJKsymbol \xeCJK_fallback_testsymbol:N + } + } +\NewDocumentCommand \xeCJKdisablefallback { } + { + \bool_if:NT \l_xeCJK_fallback_bool + { + \bool_set_false:N \l_xeCJK_fallback_bool + \cs_set_eq:NN \CJKsymbol \xeCJK_fallback_save_CJKsymbol:N + } + } % \end{macrocode} -% 抑制换行符产生的空格 -% \begin{macrocode} -\endlinechar \m@ne +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_fallback_testsymbol:N} +% 测试当前字体中是否存在当前字符,如存在则直接输出,否则启用后备字体。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_fallback_testsymbol:N + { + \font_glyph_if_exist:NnTF \tex_font:D {`#1} + { \xeCJK_fallback_save_CJKsymbol:N {#1} } + { + \xeCJK_family_if_exist:nTF { \xeCJK@family/FallBack } + { { + \tl_put_right:Nn \xeCJK@family { /FallBack } + \xeCJK_select_font: + \xeCJK_fallback_testsymbol:N {#1} + } } + { + \xeCJK_warning:nx { fallback } {#1} + \xeCJK_fallback_save_CJKsymbol:N {#1} + } + } + } +\xeCJK_msg_new:nn { fallback } + { + CJKfamily~'\xeCJK@family'~ + ( \prop_get:NV \g_xeCJK_family_prop \xeCJK@family )~ + does~not~contain~glyph~'#1'~(U+\int_to_hexadecimal:n {`#1}).\\ + } % \end{macrocode} +% \end{macro} % -% 给已有宏内容前后附加补丁 +% \begin{macro}{\setCJKfallbackfamilyfont} +% \begin{macro}[aux]{\xeCJK_set_family_fallback:nnn} % \begin{macrocode} -\def\xeCJK@patch#1#2#3{ - \edef#1{ - \unexpanded{#2} - \unexpanded\expandafter{#1} - \unexpanded{#3}}} +\NewDocumentCommand \setCJKfallbackfamilyfont { m O{} m } + { + \exp_args:Nx \tl_if_in:nnTF {#3} { , } + { \xeCJK_set_family_fallback:nnn {#1} {#2} {#3} } + { \xeCJK_set_family:nnn { #1/FallBack } {#2} {#3} } + } +\cs_new_nopar:Nn \xeCJK_set_family_fallback:nnn + { + \group_begin: + \tl_set:Nx \l_xeCJK_family_fb_tl {#1} + \prop_get:NVNF \g_xeCJK_family_prop \l_xeCJK_family_fb_tl \l_xeCJK_fontname_tl + { \tl_clear:N \l_xeCJK_fontname_tl } + \clist_map_inline:xn {#3} + { + \tl_put_right:Nn \l_xeCJK_family_fb_tl { /FallBack } + \xeCJK_get_sub_features:nn \l_xeCJK_family_fb_tl {##1} + \clist_put_left:cx { l_xeCJK_ \l_xeCJK_family_fb_tl _fontfeat_clist } {#2} + \xeCJK_set_family:ncc \l_xeCJK_family_fb_tl + { l_xeCJK_ \l_xeCJK_family_fb_tl _fontfeat_clist } + { l_xeCJK_ \l_xeCJK_family_fb_tl _fontname_tl } + } + \group_end: + } % \end{macrocode} -% \section{字符类别设定} -% \label{sec:charclass} -% \xeCJK{} 功能开关 -% \begin{macrocode} -\def\makexeCJKactive{ - \XeTeXinterchartokenstate=1\relax} - -\def\makexeCJKinactive{ - \XeTeXinterchartokenstate=0\relax} - -\makexeCJKactive +% \end{macro} +% \end{macro} +% +% +% \subsection{CJK 字体族声明方式} +% +% \begin{macrocode} +\bool_new:N \g_xeCJK_AutoFakeBold_bool +\bool_new:N \g_xeCJK_AutoFakeSlant_bool +\fp_new:N \g_xeCJK_EmboldenFactor_fp +\fp_new:N \g_xeCJK_SlantFactor_fp +% \end{macrocode} +% +% \begin{macro}{AutoFakeBold, AutoFakeSlant,EmboldenFactor,SlantFactor} +% 伪粗体和伪斜体的宏包选项声明。 +% \begin{macrocode} +\keys_define:nn { xeCJK / options } + { + AutoFakeBold .choice:, + AutoFakeBold / true .code:n = + { \bool_set_true:N \g_xeCJK_AutoFakeBold_bool }, + AutoFakeBold / false .code:n = + { \bool_set_false:N \g_xeCJK_AutoFakeBold_bool }, + AutoFakeBold / unknown .code:n = + { + \bool_set_true:N \g_xeCJK_AutoFakeBold_bool + \fp_set:Nn \g_xeCJK_EmboldenFactor_fp { \l_keys_value_tl } + }, + AutoFakeBold .default:n = { true }, + AutoFakeSlant .choice:, + AutoFakeSlant / true .code:n = + { \bool_set_true:N \g_xeCJK_AutoFakeSlant_bool }, + AutoFakeSlant / false .code:n = + { \bool_set_false:N \g_xeCJK_AutoFakeSlant_bool }, + AutoFakeSlant / unknown .code:n = + { + \bool_set_true:N \g_xeCJK_AutoFakeSlant_bool + \fp_set:Nn \g_xeCJK_SlantFactor_fp { \l_keys_value_tl } + }, + AutoFakeSlant .default:n = { true }, + EmboldenFactor .fp_set:N = \g_xeCJK_EmboldenFactor_fp, + SlantFactor .fp_set:N = \g_xeCJK_SlantFactor_fp, + BoldFont .meta:n = { AutoFakeBold = true }, + boldfont .meta:n = { AutoFakeBold = true }, + SlantFont .meta:n = { AutoFakeSlant = true }, + slantfont .meta:n = { AutoFakeSlant = true }, + } % \end{macrocode} -% 设定字符类别: -% \begin{center} -% \begin{tabular}{cll} -% \hline -% 编号 & 类别 & 例子 \\ -% \hline -% 0 & 西文一般符号 & abc \\ -% 1 & CJK 表意符号 & 汉字ぁぃぅ \\ -% 2 & 全角左标点 & (《“ \\ -% 3 & 全角右标点 & ,。)》” \\ -% 4 & 半角左标点 & ( [ \{ \\ -% 5 & 半角右标点 & , . ? ) ] \} \\ -% 6 & 前后原始间距的符号 & / \\ -% \hline -% \end{tabular} -% \end{center} -% \begin{macrocode} -\def\xeCJKsetcharclass#1#2#3{ - \@tempcnta=#1 - \loop - \XeTeXcharclass \@tempcnta #3\relax - \advance\@tempcnta 1\relax - \unless\ifnum\the\@tempcnta>#2 \repeat - \xeCJK@setpunctcharclass} - -\def\xeCJK@prePunct#1#2{\xeCJK@setPunct{2}{#1}{#2}} -\def\xeCJK@postPunct#1#2{\xeCJK@setPunct{3}{#1}{#2}} - -\def\xeCJK@setPunct#1#2#3{ - \def\xeCJK@class{#1} - \@tempcnta "#2\relax - \multiply\@tempcnta 256\relax - \xeCJK@setPunct@#3,,} - -\def\xeCJK@setPunct@#1,{ - \edef\xeCJK@temp{#1}% - \ifx\xeCJK@temp\@empty - \else - \@tempcntb "#1\relax - \advance\@tempcntb\@tempcnta\relax - \XeTeXcharclass \@tempcntb=\xeCJK@class\relax - \def\xeCJK@temp{\xeCJK@setPunct@} - \fi - \xeCJK@temp} - -\def\xeCJK@setpunctcharclass{ - \xeCJK@prePunct{20}{18,1C} - \xeCJK@postPunct{20}{19,1D,14,26} - \xeCJK@postPunct{25}{00} - \xeCJK@prePunct{30}{08,0A,0C,0E,10,12,14,16,18,1A,1D,1F,36} - - \xeCJK@postPunct{30}{01,02,05,06,09,0B,0D,0F,11,15,17,19,1B,1E, - 41,43,45,47,49,63,83,85,87,8E, - 9B,9C,9D,9E,A1,A3,A5,A7,A9,C3,E3,E5,E7,EE,F5,F6,FB,FC,FD,FE} - \xeCJK@prePunct {FE}{59,5B,5D,5F,60,69,6B} - \xeCJK@postPunct{FE}{50,51,52,54,55,56,57,5A,5C,5E,6A} - \xeCJK@prePunct {FF}{03,04,08,20,3B,5B,E0,E1,E5,E6} - \xeCJK@postPunct{FF}{01,05,09,0C,0E,1A,1B,1F,3D,5D, - 61,63,64,65,67,68,69,6A,6B,6C,6D,6E,6F,70,9E,9F} - - \xeCJK@setPunct{1}{0}{B7} - \xeCJK@setPunct{4}{0}{28,2D,5B,60,7B} - \xeCJK@setPunct{5}{0}{21,22,25,27,29,2C,2E,3A,3B,3F,5D,7D}} - +% \end{macro} +% +% \begin{macro}[internal]{\keys_set_known:nxN} +% \begin{macrocode} +\cs_generate_variant:Nn \keys_set_known:nnN { nx } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_new_sub_key:n,\g_xeCJK_sub_key_clist} +% 用于定义 CJK 子区字体和备用字体的选项。 +% \begin{macrocode} +\clist_new:N \g_xeCJK_sub_key_clist +\cs_new_nopar:Nn \xeCJK_new_sub_key:n + { + \clist_gput_right:Nx \g_xeCJK_sub_key_clist {#1} + \keys_define:nn { xeCJK / features } + { + #1 .code:n = + { + \tl_if_blank:xTF {##1} + { + \bool_set_false:c { l_xeCJK_copy_#1_bool } + \bool_set_false:c { l_xeCJK_add_#1_bool } + \tl_put_right:Nx \l_xeCJK_family_tl { /#1 } + } + { + \clist_put_right:Nx \l_xeCJK_sub_key_clist {#1} + \str_if_eq:xxTF {##1} * + { + \bool_set_true:c { l_xeCJK_copy_#1_bool } + \bool_set_false:c { l_xeCJK_add_#1_bool } + } + { + \bool_set_false:c { l_xeCJK_copy_#1_bool } + \bool_set_true:c { l_xeCJK_add_#1_bool } + \xeCJK_get_sub_features:nn {#1} {##1} + } + } + }, + #1 .default:n = \c_empty_tl, + } + } +\cs_generate_variant:Nn \xeCJK_new_sub_key:n { x } +\cs_new_nopar:Nn \xeCJK_get_sub_features:nn + { + \tl_set:Nx \l_tmpa_tl {#2} + \clist_clear:N \l_xeCJK_sub_fontfeat_clist + \xeCJK_gobble_brace:N \l_tmpa_tl + \exp_args:No \tl_if_head_eq_charcode:nNTF \l_tmpa_tl [ % ] + { + \exp_after:wN \xeCJK_get_sub_features_aux:n \l_tmpa_tl \c_empty_tl + \tl_if_blank:xT \l_xeCJK_sub_fontname_tl + { + \tl_set:Nx \l_xeCJK_sub_fontname_tl \l_tmpa_tl + \clist_clear:N \l_xeCJK_sub_fontfeat_clist + } + } + { \tl_set:Nx \l_xeCJK_sub_fontname_tl \l_tmpa_tl } + \tl_if_blank:xTF \l_xeCJK_sub_fontname_tl + { \tl_set:Nx \l_xeCJK_sub_fontname_tl \l_xeCJK_fontname_tl } + { \tl_replace_all:Nnx \l_xeCJK_sub_fontname_tl * \l_xeCJK_fontname_tl } + \clist_set:cx { l_xeCJK_#1_fontfeat_clist } \l_xeCJK_sub_fontfeat_clist + \tl_set:cx { l_xeCJK_#1_fontname_tl } \l_xeCJK_sub_fontname_tl + } % \end{macrocode} +% \end{macro} % -% 以下 Uncode 范围数据取自 fontwrap 宏包: -% \begin{itemize} -% \item Hangul Jamo +% \begin{macro}[aux] +% {\xeCJK_gobble_brace:N,\xeCJK_get_sub_features:nn,\xeCJK_get_sub_features_aux:n} % \begin{macrocode} -\xeCJKsetcharclass{"1100}{"11FF}{1} +\cs_new_nopar:Nn \xeCJK_gobble_brace:N + { + \exp_args:No \tl_if_head_group:nT #1 + { + \exp_after:wN \tl_set:Nn \exp_after:wN #1 #1 + \xeCJK_gobble_brace:N #1 + } + } +\cs_new_nopar:Npn \xeCJK_get_sub_features_aux:n [#1] #2 + { + \clist_set:Nx \l_xeCJK_sub_fontfeat_clist {#1} + \tl_set:Nx \l_xeCJK_sub_fontname_tl {#2} + } % \end{macrocode} -% \item[] 以下 |"2E80|--|"4DBF| 连续 -% \item CJK Radicals Supplement +% \end{macro} +% +% \begin{macro}{FallBack} % \begin{macrocode} -\xeCJKsetcharclass{"2E80}{"2EFF}{1} +\xeCJK_new_sub_key:n { FallBack } % \end{macrocode} -% \item Kangxi Radicals +% \end{macro} +% +% \begin{macro}[internal]{.clist_set_x:N,.clist_set_x:c} % \begin{macrocode} -\xeCJKsetcharclass{"2F00}{"2FDF}{1} +\cs_set_protected:cpn { \c_keys_props_root_tl .clist_set_x:N } #1 + { \keys_variable_set:NnN #1 { clist } x } +\cs_set_protected:cpn { \c_keys_props_root_tl .clist_set_x:c } #1 + { \keys_variable_set:cnN {#1} { clist } x } % \end{macrocode} -% \item Ideographic Description Characters +% \end{macro} +% +% \begin{macro}[internal]{\g_xeCJK_features_id_prop, BoldFont, ItalicFont, BoldItalicFont, +% SlantedFont, BoldSlantedFont,BoldFeatures, ItalicFeatures, BoldItalicFeatures, +% SlantedFeatures, BoldSlantedFeatures} +% 调用字体的属性声明,同 \pkg{fontspec} 宏包。 % \begin{macrocode} -\xeCJKsetcharclass{"2FF0}{"2FFF}{1} +\cs_new_nopar:Nn \xeCJK_map_features_id:n + { \prop_get:Nn \g_xeCJK_features_id_prop { #1 } } +\prop_new:N \g_xeCJK_features_id_prop +\prop_put:Nnn \g_xeCJK_features_id_prop { bf } { Bold } +\prop_put:Nnn \g_xeCJK_features_id_prop { it } { Italic } +\prop_put:Nnn \g_xeCJK_features_id_prop { bfit } { BoldItalic } +\prop_put:Nnn \g_xeCJK_features_id_prop { sl } { Slanted } +\prop_put:Nnn \g_xeCJK_features_id_prop { bfsl } { BoldSlanted } +\prop_map_inline:Nn \g_xeCJK_features_id_prop + { + \keys_define:nn { xeCJK / features } + { + #2Font .tl_set_x:c = { l_xeCJK_fontname_#1_tl }, + #2Features .clist_set_x:c = { l_xeCJK_fontfeat_#1_clist } , + } + } % \end{macrocode} -% \item CJK Symbolsand Punctuation -% \begin{macrocode} -\xeCJKsetcharclass{"3000}{"303F}{1} +% \end{macro} +% +% \begin{macro}[internal]{AutoFakeBold, AutoFakeSlant, Mono} +% \begin{macrocode} +\keys_define:nn { xeCJK / features } + { + AutoFakeBold .choice:, + AutoFakeBold / false .code:n = + { \bool_set_false:N \l_xeCJK_AutoFakeBold_bool }, + AutoFakeBold / unknown .code:n = + { + \bool_set_true:N \l_xeCJK_AutoFakeBold_bool + \fp_set:Nn \l_xeCJK_EmboldenFactor_fp { \l_keys_value_tl } + }, + AutoFakeBold .default:n = { \g_xeCJK_EmboldenFactor_fp }, + AutoFakeSlant .choice:, + AutoFakeSlant / false .code:n = + { \bool_set_false:N \l_xeCJK_AutoFakeSlant_bool }, + AutoFakeSlant / unknown .code:n = + { + \bool_set_true:N \l_xeCJK_AutoFakeSlant_bool + \fp_set:Nn \l_xeCJK_SlantFactor_fp { \l_keys_value_tl } + }, + AutoFakeSlant .default:n = { \g_xeCJK_SlantFactor_fp }, + Mono .choice:, + Mono / Exspace .code:n = { \xeCJK_set_monoexspace: }, + Mono / Scale .code:n = + { + \xeCJK_set_monoscale: + \tl_set:Nx \l_xeCJK_monoscale_tl + { Scale = { \fp_use:N \g_xeCJK_monoscale_fp } } + } + } % \end{macrocode} -% \item Hiragana -% \begin{macrocode} -\xeCJKsetcharclass{"3040}{"309F}{1} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_set_init:} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_set_init: + { + \tl_clear:N \l_xeCJK_monoscale_tl + \int_gincr:N \g_xeCJK_fontspec_int + \prop_clear:N \l_xeCJK_add_font_prop + \prop_map_inline:Nn \g_xeCJK_features_id_prop + { + \tl_clear:c { l_xeCJK_fontname_##1_tl } + \clist_clear:c { l_xeCJK_fontfeat_##1_clist } + } + \clist_clear:N \l_xeCJK_pass_features_clist + \clist_clear:N \l_xeCJK_sub_key_clist + \clist_map_inline:Nn \g_xeCJK_sub_key_clist + { + \bool_set_false:c { l_xeCJK_copy_##1_bool } + \bool_set_false:c { l_xeCJK_add_##1_bool } + } + \bool_set_eq:NN \l_xeCJK_AutoFakeBold_bool \g_xeCJK_AutoFakeBold_bool + \bool_set_eq:NN \l_xeCJK_AutoFakeSlant_bool \g_xeCJK_AutoFakeSlant_bool + \fp_set_eq:NN \l_xeCJK_EmboldenFactor_fp \g_xeCJK_EmboldenFactor_fp + \fp_set_eq:NN \l_xeCJK_SlantFactor_fp \g_xeCJK_SlantFactor_fp + } % \end{macrocode} -% \item Katakana -% \begin{macrocode} -\xeCJKsetcharclass{"30A0}{"30FF}{1} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_set_family:nnn} +% 设置一个 CJK 新字体族,与 |\newfontfamily| 类似,增加 |FallBack| 选项。 +% \begin{macrocode} +\cs_new_protected_nopar:Nn \xeCJK_set_family:nnn + { + \group_begin: + \xeCJK_set_init: + \tl_set:Nx \l_xeCJK_family_tl {#1} + \clist_set:Nx \l_xeCJK_fontoptions_clist {#2} + \tl_set:Nx \l_xeCJK_fontname_tl {#3} + \keys_set_known:nxN { xeCJK / features } + { \g_xeCJK_default_features_clist, #2 } \l_xeCJK_pass_features_clist + \xeCJK_parse_features: + \xeCJK_pass_features: + \cs_gset_protected_nopar:cpx { xeCJK/family/\l_xeCJK_family_tl } + { + \exp_not:n { \fontspec_set_family:Nnn \l_xeCJK_fontspec_family_tl } + { \l_xeCJK_pass_features_clist } { \l_xeCJK_fontname_tl } + \prop_gput:NnV \exp_not:N \g_xeCJK_family_name_prop + { \l_xeCJK_family_tl } \exp_not:N \l_xeCJK_fontspec_family_tl + \cs_gset_protected_nopar:cpx { xeCJK/family/\l_xeCJK_family_tl } + \exp_not:n + { { + \exp_not:N \fontencoding { \g_fontspec_encoding_tl } + \exp_not:N \fontfamily { \l_xeCJK_fontspec_family_tl } + \exp_not:N \selectfont + } } + } + \xeCJK_save_family_info: + \xeCJK_add_sub_block: + \group_end: + } +\cs_generate_variant:Nn \xeCJK_set_family:nnn { ncc } % \end{macrocode} -% \item Bopomofo +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_add_font:nn,\xeCJK_add_font_if_new:nn} % \begin{macrocode} -\xeCJKsetcharclass{"3100}{"312F}{1} +\cs_new_nopar:Nn \xeCJK_add_font:nn + { + \prop_put:Nxx \l_xeCJK_add_font_prop + { \xeCJK_map_features_id:n {#1} Font } {#2} + } +\cs_new_nopar:Nn \xeCJK_add_font_if_new:nn + { + \prop_put_if_new:Nxx \l_xeCJK_add_font_prop + { \xeCJK_map_features_id:n {#1} Font } {#2} + } +\cs_generate_variant:Nn \xeCJK_add_font:nn { nx, nc, nV, nv } +\cs_generate_variant:Nn \xeCJK_add_font_if_new:nn { nx, nc, nV, nv } % \end{macrocode} -% \item Hangul Compatibility Jamo +% \end{macro} +% % \begin{macrocode} -\xeCJKsetcharclass{"3130}{"318F}{1} +\cs_generate_variant:Nn \prop_put:Nnn { Nxx } +\cs_generate_variant:Nn \prop_get:Nn { NV } +\cs_generate_variant:Nn \prop_get:NnNF { Nx } +\cs_generate_variant:Nn \prop_get:NnNTF { Nx } +\cs_generate_variant:Nn \prop_if_in:NnF { Nx } +\cs_generate_variant:Nn \prop_put_if_new:Nnn { Nxx } % \end{macrocode} -% \item Kanbun +% +% \begin{macro}[internal]{\xeCJK_add_fake_bold:n,\xeCJK_add_fake_slant:n} % \begin{macrocode} -\xeCJKsetcharclass{"3190}{"319F}{1} +\cs_new_nopar:Nn \xeCJK_add_fake_bold:n + { + \clist_put_left:cx { l_xeCJK_fontfeat_#1_clist } + { FakeBold = { \fp_use:N \l_xeCJK_EmboldenFactor_fp } } + } +\cs_new_nopar:Nn \xeCJK_add_fake_slant:n + { + \clist_put_left:cx { l_xeCJK_fontfeat_#1_clist } + { FakeSlant = { \fp_use:N \l_xeCJK_SlantFactor_fp } } + } % \end{macrocode} -% \item Bopomofo Extended -% \begin{macrocode} -\xeCJKsetcharclass{"31A0}{"31BF}{1} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_parse_features:,\xeCJK_parse_features:n} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_parse_features: + { \prop_map_inline:Nn \g_xeCJK_features_id_prop { \xeCJK_parse_features:n {##1} } } +\cs_new_nopar:Nn \xeCJK_parse_features:n + { + \xeCJK_if_font_select:nTF {#1} + { + \xeCJK_add_font:nv {#1} { l_xeCJK_fontname_#1_tl } + \xeCJK_if_it_or_sl:nTF {#1} + { + \xeCJK_if_font_select:nF {bf#1} + { \xeCJK_add_font_if_new:nv {bf#1} { l_xeCJK_fontname_#1_tl } } + } + { + \str_if_eq:xxT {#1} {bf} + { + \clist_map_inline:nn { it , sl } + { + \xeCJK_if_font_select:nF {bf##1} + { \xeCJK_add_font:nV {bf##1} \l_xeCJK_fontname_bf_tl } + } + } + } + } + { \xeCJK_set_fake:n {#1} } + } % \end{macrocode} -% \item CJK Strokes +% \end{macro} +% +% \begin{macro}[pTF,internal]{\xeCJK_if_font_select:n,\xeCJK_if_it_or_sl:n} % \begin{macrocode} -\xeCJKsetcharclass{"31C0}{"31EF}{1} +\prg_new_conditional:Nnn \xeCJK_if_font_select:n { p, T, F, TF } + { + \exp_args:Nc + \tl_if_blank:xTF { l_xeCJK_fontname_#1_tl } \prg_return_false: \prg_return_true: + } +\prg_new_conditional:Nnn \xeCJK_if_it_or_sl:n { p, T, F, TF } + { + \bool_if:nTF { \str_if_eq_p:xx { it } {#1} || \str_if_eq_p:xx { sl } {#1} } + \prg_return_true: \prg_return_false: + } % \end{macrocode} -% \item Katakana Phonetic Extensions -% \begin{macrocode} -\xeCJKsetcharclass{"31F0}{"31FF}{1} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_set_fake:n} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_set_fake:n + { + \str_if_eq:xxTF {#1} { bf } + { \bool_if:NT \l_xeCJK_AutoFakeBold_bool { \xeCJK_add_fake_bold:n {#1} } } + { + \bool_if:NTF \l_xeCJK_AutoFakeSlant_bool + { + \bool_if:nT + { \xeCJK_if_it_or_sl_p:n {#1} || + ( \str_if_eq_p:xx {#1} {bfit} && ! ( \xeCJK_if_font_select_p:n {it} ) ) || + ( \str_if_eq_p:xx {#1} {bfsl} && ! ( \xeCJK_if_font_select_p:n {sl} ) ) + } + { \xeCJK_add_fake_slant:n {#1} } + } + { \xeCJK_if_it_or_sl:nT {#1} { \xeCJK_map_it_sl:n {#1} } } + \bool_if:nT + { \l_xeCJK_AutoFakeBold_bool + && ! ( \xeCJK_if_it_or_sl_p:n {#1} ) + && ! ( \xeCJK_if_font_select_p:n {bf} ) + } + { \xeCJK_add_fake_bold:n {#1} } + } + \xeCJK_add_font_if_new:nn {#1} * + } % \end{macrocode} -% \item Enclosed CJK Letters and Months +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_map_it_sl:n} % \begin{macrocode} -\xeCJKsetcharclass{"3200}{"32FF}{1} +\cs_new_nopar:Nn \xeCJK_map_it_sl:n + { + \xeCJK_if_map_font_select:nT {#1} + { + \xeCJK_add_font:nx {#1} { \xeCJK_get_map_font:n {#1} } + \xeCJK_if_font_select:nF {bf#1} + { \xeCJK_add_font_if_new:nx {bf#1} { \xeCJK_get_map_font:n {#1} } } + } + } % \end{macrocode} -% \item CJK Compatibility +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_get_map_font:n} % \begin{macrocode} -\xeCJKsetcharclass{"3300}{"33FF}{1} +\cs_new_nopar:Nn \xeCJK_get_map_font:n + { \tl_use:c { l_xeCJK_fontname_\str_if_eq:xxTF {#1} {it} {sl} {it} _tl } } % \end{macrocode} -% \item CJKUnified Ideographs Extension A +% \end{macro} +% +% \begin{macro}[pTF,internal]{\xeCJK_if_map_font_select:n} % \begin{macrocode} -\xeCJKsetcharclass{"3400}{"4DBF}{1} +\prg_new_conditional:Nnn \xeCJK_if_map_font_select:n { p, T, F, TF } + { + \tl_if_blank:xTF { \xeCJK_get_map_font:n {#1} } + \prg_return_false: \prg_return_true: + } % \end{macrocode} -% \item[] 以下块不连续 -% \item CJK Unified Ideographs -% \begin{macrocode} -\xeCJKsetcharclass{"4E00}{"9FFF}{1} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_pass_features:} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_pass_features: + { + \prop_map_inline:Nn \g_xeCJK_features_id_prop + { + \clist_if_empty:cF { l_xeCJK_fontfeat_##1_clist } + { + \clist_put_right:Nx \l_xeCJK_pass_features_clist + { ##2Features = { \clist_use:c { l_xeCJK_fontfeat_##1_clist } } } + } + } + \prop_map_inline:Nn \l_xeCJK_add_font_prop + { \clist_put_right:Nx \l_xeCJK_pass_features_clist { ##1 = { ##2 } } } + \tl_if_blank:xF \l_xeCJK_monoscale_tl + { \clist_put_right:Nx \l_xeCJK_pass_features_clist \l_xeCJK_monoscale_tl } + } % \end{macrocode} -% \item Yi +% \end{macro} +% +% \begin{macro}[internal,var] +% {\g_xeCJK_family_prop,\g_xeCJK_family_name_prop,\g_xeCJK_family_options_prop} % \begin{macrocode} -\xeCJKsetcharclass{"A000}{"A4CF}{1} +\prop_new:N \g_xeCJK_family_prop +\prop_new:N \g_xeCJK_family_name_prop +\prop_new:N \g_xeCJK_family_options_prop % \end{macrocode} -% \item Hangul Syllables +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_save_family_info:} % \begin{macrocode} -\xeCJKsetcharclass{"AC00}{"D7AF}{1} +\cs_new_nopar:Nn \xeCJK_save_family_info: + { + \group_begin: + \clist_map_inline:Nn \g_xeCJK_CJK_subclass_clist + { + \clist_remove_all:Nn \l_xeCJK_fontoptions_clist {##1} + \clist_remove_all:Nn \l_xeCJK_fontoptions_clist { ##1 = } + } + \prop_gput:NVV \g_xeCJK_family_prop + \l_xeCJK_family_tl \l_xeCJK_fontname_tl + \prop_gput:NVV \g_xeCJK_family_options_prop + \l_xeCJK_family_tl \l_xeCJK_fontoptions_clist + \group_end: + } % \end{macrocode} -% \item CJK Compatibility Ideographs -% \begin{macrocode} -\xeCJKsetcharclass{"F900}{"FAFF}{1} +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_add_sub_block:} +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_add_sub_block: + { + \clist_remove_duplicates:N \l_xeCJK_sub_key_clist + \clist_map_inline:Nn \l_xeCJK_sub_key_clist + { + \tl_set:Nx \l_tmpa_tl { \l_xeCJK_family_tl/##1 } + \bool_if:cT { l_xeCJK_copy_##1_bool } + { + \tl_map_inline:nn { \g_xeCJK_family_prop \g_xeCJK_family_options_prop } + { + \prop_get:NVNT ####1 \l_xeCJK_family_tl \l_tmpb_tl + { \prop_gput:NVV ####1 \l_tmpa_tl \l_tmpb_tl } + } + \prop_get:NVNT \g_xeCJK_family_options_prop \l_tmpa_tl \l_tmpa_clist + { + \clist_remove_all:Nn \l_tmpa_clist { ##1 = * } + \prop_gput:NVV \g_xeCJK_family_options_prop \l_tmpa_tl \l_tmpa_clist + } + \cs_gset_protected_nopar:cpx { xeCJK/family/\l_tmpa_tl } + { + \exp_not:N \xeCJK_family_if_exist:nT { \l_xeCJK_family_tl } + { + \prop_get:NnNT \exp_not:N \g_xeCJK_family_name_prop + { \l_xeCJK_family_tl } \exp_not:N \l_tmpa_tl + { + \prop_gput:NnV \exp_not:N \g_xeCJK_family_name_prop + { \l_tmpa_tl } \exp_not:N \l_tmpa_tl + \cs_gset_protected_nopar:cpx { xeCJK/family/\l_tmpa_tl } + \exp_not:n + { { + \exp_not:N \fontencoding { \g_fontspec_encoding_tl } + \exp_not:N \fontfamily { \l_tmpa_tl } + \exp_not:N \selectfont + } } + } + } + } + } + \bool_if:cT { l_xeCJK_add_##1_bool } + { + \xeCJK_set_family:ncc \l_tmpa_tl + { l_xeCJK_##1_fontfeat_clist } { l_xeCJK_##1_fontname_tl } + } + } + } % \end{macrocode} -% \item CJK Compatibility Forms +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_copy_family:nn} % \begin{macrocode} -\xeCJKsetcharclass{"FE30}{"FE4F}{1} +\cs_new_nopar:Nn \xeCJK_copy_family:nn + { + \xeCJK_family_if_exist:nT {#2} + { + \tl_map_inline:nn + { \g_xeCJK_family_prop \g_xeCJK_family_options_prop \g_xeCJK_family_name_prop } + { \prop_get:NnNT ##1 {#2} \l_tmpa_tl { \prop_gput:NnV ##1 {#1} \l_tmpa_tl } } + \cs_gset_eq:cc { xeCJK/family/#1 } { xeCJK/family/#2 } + } + } +\cs_generate_variant:Nn \xeCJK_copy_family:nn { xx } % \end{macrocode} -% \item Halfwidth and Fullwidth Forms +% \end{macro} +% +% \subsection{字体切换} +% +% \begin{macro}[internal]{\l_xeCJK_font_coor_tl,\xeCJK_select_font:,\xeCJK_switch_font:nn} +% 缓存当前字体的原始格式,以加速编译。 % \begin{macrocode} -\xeCJKsetcharclass{"FF00}{"FFEF}{1} +\tl_set:Nn \l_xeCJK_font_coor_tl { xeCJK/\xeCJK@family/\f@series/\f@shape/\f@size } +\cs_new_nopar:Nn \xeCJK_select_font: + { + \cs_if_exist_use:cF \l_xeCJK_font_coor_tl + { + \tl_set:Nx \l_xeCJK_current_coor_tl \l_xeCJK_font_coor_tl + \cs_if_exist_use:cT { xeCJK/family/\xeCJK@family } + { \exp_last_unbraced:NNV \cs_gset_eq:cN \l_xeCJK_current_coor_tl \font@name } + } + } +\cs_new_eq:NN \xeCJK@setfont \xeCJK_select_font: +\cs_new_nopar:Nn \xeCJK_switch_font:nn + { + \str_if_eq:xxF {#1} {#2} + { + \xeCJK_info:nxx { CJK-block } {#1} {#2} + \tl_remove_all:Nn \xeCJK@family { /#1 } + \str_if_eq:xxF {#2} { CJK } + { + \tl_set:Nx \l_tmpa_tl \xeCJK@family + \tl_put_right:Nx \xeCJK@family { /#2 } + \xeCJK_family_if_exist:nF \xeCJK@family + { + \xeCJK_family_if_exist:nTF { \CJKfamilydefault/#2 } + { \xeCJK_copy_family:xx \xeCJK@family { \CJKfamilydefault/#2 } } + { \xeCJK_copy_family:xx \xeCJK@family \l_tmpa_tl } + } + } + } + \xeCJK_select_font: + } +\xeCJK_msg_new:nn { CJK-block } { Switch~from~block~'#1'~to~'#2'. } % \end{macrocode} -% \item CJK Unified Ideographs Extension B +% \end{macro} +% +% \begin{macro}[TF,internal]{\xeCJK_family_if_exist:n} % \begin{macrocode} -\xeCJKsetcharclass{"20000}{"2A6DF}{1} +\prg_new_conditional:Nnn \xeCJK_family_if_exist:n { T, F, TF } + { + \cs_if_free:cTF { xeCJK/family/#1 } \prg_return_false: + { + \prop_if_in:NxF + \g_xeCJK_family_name_prop {#1} { \use:c { xeCJK/family/#1 } } + \prg_return_true: + } + } % \end{macrocode} -% \item CJK Unified Ideographs Extension C -% \begin{macrocode} -\xeCJKsetcharclass{"2A700}{"2B73F}{1} +% \end{macro} +% +% \begin{macro}{\CJKfamily} +% 用于切换 CJK 字体族。 +% \begin{macrocode} +\NewDocumentCommand \CJKfamily { m } + { + \xeCJK_family_if_exist:nTF {#1} + { \tl_set:Nx \xeCJK@family {#1} } + { + \cs_if_free:cT { xeCJK_warned_aux_#1 } + { + \xeCJK_warning:nx { CJKfamily-Unknown } {#1} + \tl_new:c { xeCJK_warned_aux_#1 } + } + } + } +\xeCJK_msg_new:nn { CJKfamily-Unknown } + { + Unknown~CJK~family~'#1'~is~ignored.\\\\ + Try~to~use~ + \prg_case_str:xxn {#1} + { + \CJKrmdefault { \token_to_str:N \setCJKmainfont } + \CJKsfdefault { \token_to_str:N \setCJKsansfont } + \CJKttdefault { \token_to_str:N \setCJKmonofont } + } + { \token_to_str:N \setCJKfamilyfont {#1} } + [...]{...}~to~define~it. + } % \end{macrocode} -% \item CJK Unified Ideographs Extension D -% \begin{macrocode} -\xeCJKsetcharclass{"2B740}{"2B81F}{1} +% \end{macro} +% +% \begin{macro}{\setCJKfamilyfont, \newCJKfontfamily, \CJKfontspec} +% 分别用于预声明 CJK 字体和随机调用 CJK 字体。 +% \begin{macrocode} +\NewDocumentCommand \setCJKfamilyfont { m O{} m } + { \xeCJK_set_family:nnn {#1} {#2} {#3} } +\NewDocumentCommand \newCJKfontfamily { o m O{} m } + { + \IfNoValueTF {#1} + { \tl_set:Nx \l_xeCJK_family_tl { \cs_to_str:N #2 } } + { \tl_set:Nx \l_xeCJK_family_tl {#1} } + \xeCJK_set_family:nnn \l_xeCJK_family_tl {#3} {#4} + \cs_new_protected_nopar:Npx #2 + { \exp_not:N \CJKfamily { \l_xeCJK_family_tl } } + } +\int_new:N \g_xeCJK_fontspec_int +\int_gdecr:N \g_xeCJK_fontspec_int +\NewDocumentCommand \CJKfontspec { O{} m } + { + \tl_set:Nx \l_xeCJK_CJKfontspec_id_tl { CJKfontspec/#1/#2/id } + \cs_if_free:cT \l_xeCJK_CJKfontspec_id_tl + { + \int_gincr:N \g_xeCJK_fontspec_int + \tl_gset:Nx \g_xeCJK_family_spec_tl + { CJKfontspec ( \int_use:N \g_xeCJK_fontspec_int ) } + \xeCJK_set_family:nnn \g_xeCJK_family_spec_tl {#1} {#2} + \tl_gset:cx \l_xeCJK_CJKfontspec_id_tl \g_xeCJK_family_spec_tl + } + \exp_args:Nv \CJKfamily \l_xeCJK_CJKfontspec_id_tl + \tex_ignorespaces:D + } % \end{macrocode} -% \item CJK Compatibility Ideographs Supplement +% \end{macro} +% +% \begin{macro}{\defaultCJKfontfeatures, \addCJKfontfeatures} +% 分别用于设置 CJK 字体的默认属性和增加当前 CJK 字体的属性。 +% \begin{macrocode} +\clist_new:N \g_xeCJK_default_features_clist +\NewDocumentCommand \defaultCJKfontfeatures { m } + { \clist_gset:Nn \g_xeCJK_default_features_clist {#1} } +\@onlypreamble \defaultCJKfontfeatures +\NewDocumentCommand \addCJKfontfeatures { m } + { + \prop_if_in:NVTF \g_xeCJK_family_prop \xeCJK@family + { + \group_begin: + \clist_set:Nx \l_tmpa_clist {#1} + \prop_get:NVN \g_xeCJK_family_prop \xeCJK@family \l_tmpa_tl + \clist_map_inline:Nn \g_xeCJK_CJK_subclass_clist + { + \clist_if_in:NnT \l_tmpa_clist {##1} + { + \clist_remove_all:Nn \l_tmpa_clist {##1} + \prop_get:NxNF \g_xeCJK_family_prop + { \xeCJK@family/##1 } \l_tmpb_tl + { + \prop_get:NxNF \g_xeCJK_family_prop + { \CJKfamilydefault/##1 } \l_tmpb_tl + { \tl_set:Nx \l_tmpb_tl \l_tmpa_tl } + } + \clist_set:Nx \l_tmpa_clist + { ##1 = { [ \l_tmpa_clist ] { \l_tmpb_tl } } } + \clist_map_break: + } + } + \prop_get:NVNF \g_xeCJK_family_options_prop \xeCJK@family + \l_tmpb_clist { \clist_clear:N \l_tmpb_clist } + \clist_clear:N \l_tmpc_clist + \clist_map_inline:Nn \l_tmpb_clist + { + \clist_if_in:NnF \l_tmpa_clist {##1} + { \clist_put_right:Nn \l_tmpc_clist {##1} } + } + \clist_put_left:NV \l_tmpa_clist \l_tmpc_clist + \use:x + { \group_end: \exp_not:N \CJKfontspec [ \l_tmpa_clist ] { \l_tmpa_tl } } + } + { \xeCJK_warning:n { addCJKfontfeature-ignored } } + \tex_ignorespaces:D + } +\cs_new_eq:NN \addCJKfontfeature \addCJKfontfeatures +\xeCJK_msg_new:nn { addCJKfontfeature-ignored } + { + \tl_to_str:N \addCJKfontfeatures (s)~ignored.\\\\ + It~cannot~be~used~with~a~font~that~wasn't~selected~by~xeCJK. + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\setCJKmainfont,\setCJKsansfont} +% 设置文档的 CJK 普通字体、无衬线字体。 % \begin{macrocode} -\xeCJKsetcharclass{"2F800}{"2FA1F}{1} +\NewDocumentCommand \setCJKmainfont { O{} m } + { \xeCJK_set_family:nnn \CJKrmdefault {#1} {#2} } +\cs_new_eq:NN \setCJKromanfont \setCJKmainfont +\NewDocumentCommand \setCJKsansfont { O{} m } + { \xeCJK_set_family:nnn \CJKsfdefault {#1} {#2} } % \end{macrocode} -% \end{itemize} +% \end{macro} +% +% \begin{macro}{\CJKrmdefault,\CJKsfdefault,\CJKttdefault,\CJKfamilydefault} % \begin{macrocode} - -\def\CJK@stop{\CJK@stop} - -\def\normalspacedchars#1{ - \xeCJK@setnormalspacedchar#1\CJK@stop} - -\def\xeCJK@setnormalspacedchar#1{ - \ifx#1\CJK@stop - \else - \XeTeXcharclass`#1=6 - \expandafter\xeCJK@setnormalspacedchar - \fi} - -\normalspacedchars{/} - +\cs_if_free:NT \CJKrmdefault { \tl_set:Nn \CJKrmdefault { rm } } +\cs_if_free:NT \CJKsfdefault { \tl_set:Nn \CJKsfdefault { sf } } +\cs_if_free:NT \CJKttdefault { \tl_set:Nn \CJKttdefault { tt } } +\cs_if_free:NT \CJKfamilydefault { \tl_set:Nn \CJKfamilydefault { \CJKrmdefault } } +\tl_new:c { xeCJK/family/\CJKfamilydefault } % \end{macrocode} +% \end{macro} % -% 单独处理宽度有分歧的几个标点:包括省略号、破折号、间隔号、引号等中西文混用的 -% 符号,保证其命令形式输出的是西文字体。并对一些编码的符号宏包做特殊处理: -% \begin{macrocode} -\AtBeginDocument{% - \xeCJK@patch\textellipsis {\begingroup\makexeCJKinactive}{\endgroup} - \xeCJK@patch\textemdash {\begingroup\makexeCJKinactive}{\endgroup} - \xeCJK@patch\textperiodcentered {\begingroup\makexeCJKinactive}{\endgroup} - \xeCJK@patch\textcentereddot {\begingroup\makexeCJKinactive}{\endgroup} - \xeCJK@patch\textquoteleft {\begingroup\makexeCJKinactive}{\endgroup} - \xeCJK@patch\textquoteright {\begingroup\makexeCJKinactive}{\endgroup} - \xeCJK@patch\textquotedblleft {\begingroup\makexeCJKinactive}{\endgroup} - \xeCJK@patch\textquotedblright {\begingroup\makexeCJKinactive}{\endgroup} - \xeCJK@patch\tipaencoding {\makexeCJKinactive}{} % tipa package in T3 encoding - \let\xeCJK@save@r\r - \def\r#1{{\makexeCJKinactive\xeCJK@save@r{#1}}} % \r{u} in T1 encoding - \@ifpackageloaded{pifont}{ % pifont package in U encoding - \renewcommand\Pifont[1]{\fontfamily{#1}\fontencoding{U}% - \fontseries{m}\fontshape{n}\selectfont\makexeCJKinactive}}{} -} -% \end{macrocode} -% -% \section{字符输出规则} -% \begin{macrocode} -\XeTeXinterchartoks 1 0{\egroup\CJKecglue} -\XeTeXinterchartoks 1 1{\xeCJK@i@i} -\XeTeXinterchartoks 1 2{\xeCJK@i@ii} -\XeTeXinterchartoks 1 3{\xeCJK@i@iii} -\XeTeXinterchartoks 1 4{\egroup\CJKecglue} -\XeTeXinterchartoks 1 5{\egroup} -\XeTeXinterchartoks 1 255{\xeCJK@i@cclv} - -\XeTeXinterchartoks 2 0{\xeCJK@ii@} -\XeTeXinterchartoks 2 1{\xeCJK@ii@i} -\XeTeXinterchartoks 2 2{\xeCJK@ii@ii} -\XeTeXinterchartoks 2 3{\xeCJK@ii@iii} -\XeTeXinterchartoks 2 4{\xeCJK@ii@iv} -\XeTeXinterchartoks 2 5{\xeCJK@ii@v} -\XeTeXinterchartoks 2 255{\xeCJK@ii@cclv} - -\XeTeXinterchartoks 3 0{\xeCJK@iii@} -\XeTeXinterchartoks 3 1{\xeCJK@iii@i} -\XeTeXinterchartoks 3 2{\xeCJK@iii@ii} -\XeTeXinterchartoks 3 3{\xeCJK@iii@iii} -\XeTeXinterchartoks 3 4{\xeCJK@iii@iv} -\XeTeXinterchartoks 3 5{\xeCJK@iii@v} -\XeTeXinterchartoks 3 255{\xeCJK@iii@cclv} - -\XeTeXinterchartoks 0 1{\xeCJK@@i} -\XeTeXinterchartoks 0 2{\xeCJK@@ii} -\XeTeXinterchartoks 0 3{\xeCJK@@iii} -\XeTeXinterchartoks 0 255{\xeCJK@@cclv} - -\XeTeXinterchartoks 4 1{\xeCJK@iv@i} -\XeTeXinterchartoks 4 2{\xeCJK@iv@ii} -\XeTeXinterchartoks 4 3{\xeCJK@iv@iii} - -\XeTeXinterchartoks 5 1{\xeCJK@v@i} -\XeTeXinterchartoks 5 2{\xeCJK@v@ii} -\XeTeXinterchartoks 5 3{\xeCJK@v@iii} -\XeTeXinterchartoks 5 255{\xeCJK@v@cclv} - -\XeTeXinterchartoks 255 0{\xeCJK@cclv@} -\XeTeXinterchartoks 255 1{\xeCJK@cclv@i} -\XeTeXinterchartoks 255 2{\xeCJK@cclv@ii} -\XeTeXinterchartoks 255 3{\xeCJK@cclv@iii} -\XeTeXinterchartoks 255 4{\xeCJK@cclv@iv} - -\XeTeXinterchartoks 1 6{\xeCJK@i@vi} -\XeTeXinterchartoks 2 6{\xeCJK@ii@vi} -\XeTeXinterchartoks 3 6{\xeCJK@iii@vi} -\XeTeXinterchartoks 6 1{\xeCJK@vi@i} -\XeTeXinterchartoks 6 2{\xeCJK@vi@ii} -\XeTeXinterchartoks 6 3{\xeCJK@vi@iii} - -\def\xeCJK@vi@i{ - \bgroup - \xeCJK@emptyCJKtoks - \xeCJK@setfont - \CJKsymbol} - -\def\xeCJK@i@vi{ - \egroup} - -\let\xeCJK@ii@vi \xeCJK@i@vi -\let\xeCJK@iii@vi\xeCJK@i@vi - -\let\xeCJK@vi@ii \xeCJK@vi@i -\let\xeCJK@vi@iii\xeCJK@vi@i - -\def\xeCJK@i@i{ - \CJKglue - \CJKsymbol} - -\def\xeCJK@i@ii#1{ - \xeCJK@punctrule{#1}{l} - \hskip \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @lglue@#1\endcsname - plus 0.1em minus 0.1 em - \xeCJK@setprepunct{#1}} - -\def\xeCJK@i@iii#1{ - \xeCJK@punctrule{#1}{r} - \ifcsname xeCJK@specialpunct#1\endcsname - \CJKglue % breakable - \else - \nobreak - \fi - \global\edef\xeCJK@lastpunct{#1} - \CJKpunctsymbol{#1}} - -\def\xeCJK@setprepunct#1{ - \edef\xeCJK@lastpunct{#1} - \vrule width \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname - @lrule@#1\endcsname depth \z@ height \z@ - \CJKpunctsymbol{#1}} - -\def\xeCJK@i@cclv{ - \egroup - {\xeCJK@CJKkern} - \xeCJK@ignorespaces} - -\def\xeCJK@ii@i{ - \nobreak - \CJKsymbol} - -\def\xeCJK@ii@ii#1{ - \nobreak - \xeCJK@punctrule{#1}{l} - \xeCJK@setkern{\xeCJK@lastpunct}{#1} - \kern \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @kern\xeCJK@lastpunct#1\endcsname - \xeCJK@setprepunct{#1}} - -\def\xeCJK@ii@iii#1{ - \nobreak - \xeCJK@punctrule{#1}{r} - \xeCJK@setkern{\xeCJK@lastpunct}{#1} - \kern \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @kern\xeCJK@lastpunct#1\endcsname - \nobreak - \edef\xeCJK@lastpunct{#1} - \CJKpunctsymbol{#1}} - -\def\xeCJK@ii@{ - \nobreak - \egroup} - -\let\xeCJK@ii@iv\xeCJK@ii@ -\let\xeCJK@ii@v\xeCJK@ii@ - -\def\xeCJK@ii@cclv{ - \nobreak - \egroup - \ignorespaces} - -\def\xeCJK@iii@{ - \xeCJK@afterpostpunct - \egroup} - -\def\xeCJK@iii@i{ - \xeCJK@afterpostpunct - \CJKsymbol} - -\def\xeCJK@iii@ii#1{ - \vrule width \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname - @rrule@\xeCJK@lastpunct\endcsname depth \z@ height \z@ - \xeCJK@punctrule{#1}{l} - \xeCJK@setkern{\xeCJK@lastpunct}{#1} - \kern \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @kern\xeCJK@lastpunct#1\endcsname - \xeCJKpunctnobreak - \xeCJK@setprepunct{#1}} - -\def\xeCJK@iii@iii#1{ - \vrule width \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname - @rrule@\xeCJK@lastpunct\endcsname depth \z@ height \z@ - \xeCJK@punctrule{#1}{r} - \xeCJK@setkern{\xeCJK@lastpunct}{#1} - \kern \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @kern\xeCJK@lastpunct#1\endcsname - \nobreak - \edef\xeCJK@lastpunct{#1} - \CJKpunctsymbol{#1}} - -\def\xeCJK@iii@iv{ - \xeCJK@afterpostpunct - \egroup} - -\def\xeCJK@afterpostpunct{ - \vrule width \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname - @rrule@\xeCJK@lastpunct\endcsname depth \z@ height \z@ - \hskip \csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @rglue@\xeCJK@lastpunct\endcsname - plus 0.1em minus 0.1 em} -\let\xeCJK@iii@v\xeCJK@iii@iv - -\def\xeCJK@iii@cclv{ - \xeCJK@afterpostpunct - \egroup - \ignorespaces} - -\def\xeCJK@@i{ - \CJKecglue - \bgroup - \xeCJK@setfont - \xeCJK@emptyCJKtoks - \CJKsymbol} - -\def\xeCJK@@ii{ - \bgroup - \xeCJK@setfont - \XeTeXinterchartoks 0 2{\relax} - \xeCJK@emptyCJKtoks - \xeCJK@i@ii} - -\def\xeCJK@@iii{ - \bgroup - \xeCJK@setfont - \XeTeXinterchartoks 0 3{\relax} - \xeCJK@emptyCJKtoks - \xeCJK@i@iii} - -\def\xeCJK@iv@i{ - \bgroup - \xeCJK@setfont - \XeTeXinterchartoks 4 1{\relax} - \xeCJK@emptyCJKtoks - \CJKsymbol} - -\def\xeCJK@iv@ii{ - \bgroup - \xeCJK@setfont - \XeTeXinterchartoks 4 2{\relax} - \xeCJK@emptyCJKtoks - \xeCJK@i@ii} - -\def\xeCJK@iv@iii{ - \bgroup - \xeCJK@setfont - \XeTeXinterchartoks 4 3{\relax} - \xeCJK@emptyCJKtoks - \xeCJK@i@iii} - -\def\xeCJK@v@i{ - \CJKecglue - \bgroup - \xeCJK@setfont - \xeCJK@emptyCJKtoks - \CJKsymbol} - -\def\xeCJK@v@ii{ - \bgroup - \xeCJK@setfont - \XeTeXinterchartoks 5 2{\relax} - \xeCJK@emptyCJKtoks - \xeCJK@i@ii} - -\def\xeCJK@v@iii{ - \bgroup - \xeCJK@setfont - \XeTeXinterchartoks 5 3{\relax} - \xeCJK@emptyCJKtoks - \xeCJK@i@iii} - -\def\xeCJK@emptyCJKtoks{ - \XeTeXinterchartoks 255 1{\relax} - \XeTeXinterchartoks 255 2{\relax} - \XeTeXinterchartoks 255 3{\relax}} - -\def\xeCJK@@cclv{ - \futurelet\xeCJK@nexttoken\xeCJK@zz@cclv} - -\def\xeCJK@zz@cclv{ - \ifx\xeCJK@nexttoken\@sptoken - \else - {\xeCJK@zerokern} - \fi} - -\let\xeCJK@v@cclv\xeCJK@@cclv - -\def\xeCJK@cclv@{ - \ifnum\lastkern=\@ne - \@sptoken%\CJKecglue - \fi} -\let\xeCJK@cclv@iv\xeCJK@cclv@ - -\def\xeCJK@cclv@i{{ - \ifnum\lastkern=\@ne - \CJKglue - \else - \ifnum\lastkern=\xeCJK@four - \@sptoken%\CJKecglue - \else - \ifnum\lastnodetype=\xeCJK@ten - \CJKecglue - \fi - \fi - \fi} - \bgroup - - \xeCJK@emptyCJKtoks - \xeCJK@setfont - \CJKsymbol} - -\def\xeCJK@cclv@ii{ - \bgroup - \xeCJK@emptyCJKtoks - \xeCJK@setfont - \xeCJK@i@ii} - -\def\xeCJK@cclv@iii{ - \bgroup - \xeCJK@emptyCJKtoks - \xeCJK@setfont - \xeCJK@i@iii} - -\def\CJKglue{\hskip \z@ \@plus .08\baselineskip} -\def\CJK@nobreakglue{\nobreak\CJKglue\nobreak} - -\edef\xeCJK@CJKkern{\kern -1sp\kern 1sp} -\edef\xeCJK@prepunctkern{\kern -2sp\kern 2sp} -\edef\xeCJK@zerokern{\kern -4sp\kern 4sp} - -\chardef\xeCJK@four=4 -\chardef\xeCJK@ten=10 - +% 补丁 |\normalfont|,|\rmfamily|,|\sffamily| 和 |\ttfamily|,使其同时对 +% CJK 字体族有效。 +% \begin{macrocode} +\AtEndOfPackage + { + \etex_protected:D \tl_put_right:Nn \normalfont { \CJKfamily \CJKfamilydefault } + \etex_protected:D \tl_put_right:Nn \rmfamily { \CJKfamily \CJKrmdefault } + \etex_protected:D \tl_put_right:Nn \sffamily { \CJKfamily \CJKsfdefault } + \etex_protected:D \tl_put_right:Nn \ttfamily { \CJKfamily \CJKttdefault } + \cs_set_eq:NN \reset@font \normalfont + } % \end{macrocode} % -% 处理省略 CJK 文字间空格的代码。\verb+\CJKspace+ 保留 CJK 文字之间的空格(仍 -% 忽略标点相关空格);\verb+\CJKnospace+ 忽略 CJK 文字之间的空格。默认使用 -% \verb+\CJKnospace+。 +% \begin{macro}{\setCJKmathfont} +% 设置 CJK 数学字体。 % \begin{macrocode} -\def\CJKspace{\let\xeCJK@ignorespaces\@empty} -\def\CJKnospace{\let\xeCJK@ignorespaces\xeCJK@@ignorespaces} -\ifxeCJK@space@ - \AtEndOfPackage{\CJKspace} -\else - \AtEndOfPackage{\CJKnospace} -\fi - -\def\xeCJK@@ignorespaces{ - \futurelet\xeCJK@nexttoken\xeCJK@checknext} - -\def\xeCJK@checknext{ - \ifx\xeCJK@nexttoken\@sptoken - \expandafter\xeCJK@@checknext - \else - \ifx $\xeCJK@nexttoken - \CJKecglue - \fi - \fi} - -{ - \def\:{\xeCJK@@checknext} - \global\expandafter\def\: {\futurelet\@let@token\xeCJK@@@checknext} -} - -\def\xeCJK@@@checknext{ - \ifx $\@let@token - \@sptoken%\CJKecglue - \else - \if\relax\noexpand\@let@token - \ifx\@let@token\xeCJK@par - \else - \@sptoken - \fi - \fi - \fi - \let\xeCJK@nexttoken\relax} - -\long\def\xeCJK@gobble#1\CJK@stop{} - +\NewDocumentCommand \setCJKmathfont { O{} m } + { \xeCJK_set_family:nnn \c_xeCJK_math_tl {#1} {#2} } % \end{macrocode} +% \end{macro} % -% 避免单个汉字占一行。 +% \begin{macro}{CJKmath} +% 数学公式内的 CJK 字体。 % \begin{macrocode} - -\def\xeCJK@checksingle#1{ - \def\xeCJK@setcurrentchar@i{ - \CJKglue - \CJKsymbol{#1}} - \def\xeCJK@setcurrentnobreakchar@i{ - \CJKsymbol{#1}} - \futurelet\@let@token\xeCJK@@checksingle} - -\def\xeCJK@@checksingle{ - \ifcat 。\noexpand\@let@token - \expandafter\xeCJK@@@checksingle - \else - \expandafter\xeCJK@setcurrentchar@i - \fi} - -\def\xeCJK@@@checksingle#1{ - \def\xeCJK@setcurrentchar@ii{ - \xeCJK@setcurrentchar@i #1} - \def\xeCJK@setcurrentchar@ii@s{ - \xeCJK@setcurrentchar@i #1 } - \def\xeCJK@setcurrentnobreakchar@ii{ - \xeCJK@setcurrentnobreakchar@i #1} - \futurelet\@let@token\xeCJK@@@@checksingle} - -\def\xeCJK@@@@checksingle{ - \ifx\@let@token\@sptoken - \expandafter\xeCJK@checkpar - \else - \expandafter\xeCJK@setcurrentchar@ii - \fi} - -\let\xeCJK@par\par -\def\xeCJK@checkpar{ - \@ifnextchar\xeCJK@par{\xeCJK@setcurrentnobreakchar@ii}{\xeCJK@setcurrentchar@ii@s}} +\tl_const:Nn \c_xeCJK_math_tl { CJKmath } +\keys_define:nn { xeCJK / options } { CJKmath .bool_gset:N = \g_xeCJK_math_bool } % \end{macrocode} +% \end{macro} % -% 设置中英文间距。 +% \begin{macro}[internal]{\xeCJKsetmathcode} % \begin{macrocode} - -\def\xeCJKsetecglue#1{ - \def\CJK@ecglue{#1} - \let\CJKecglue\CJK@ecglue} -\let\CJKsetecglue\xeCJKsetecglue -\CJKsetecglue{ } - +\NewDocumentCommand \xeCJKsetmathcode { m m m m } + { + \xeCJK_check_num_range:nnNN {#1} {#2} \l_tmpa_int \l_tmpb_int + \int_set:Nn \l_tmpc_int { \xeCJK_math_type:n {#3} } + \loop + \XeTeXmathcode \l_tmpa_int = \l_tmpc_int \use:c { sym #4 } \l_tmpa_int + \if_int_compare:w \l_tmpa_int < \l_tmpb_int + \int_incr:N \l_tmpa_int + \repeat + } +\cs_set_eq:NN \xeCJK_math_type:n \mathchar@type +% \end{macrocode} +% \end{macro} +% +% 当没有设置 CJK 数学字体时,使用 |\CJKfamilydefault| 作为数学字体。 +% \begin{macrocode} +\tl_put_left:Nn \document + { + \group_end: + \prop_if_empty:NTF \g_xeCJK_family_prop + { \xeCJK_warning:n { no-CJKfamily } } + { + \bool_if:NT \g_xeCJK_math_bool + { + \xeCJK_family_if_exist:nTF \c_xeCJK_math_tl + { \tl_set:Nx \l_tmpa_tl \c_xeCJK_math_tl } + { + \xeCJK_family_if_exist:nTF \CJKfamilydefault + { \tl_set:Nx \l_tmpa_tl \CJKfamilydefault } + { \tl_set_eq:NN \l_tmpa_tl \q_no_value } + } + \prop_get:NVNT \g_xeCJK_family_name_prop \l_tmpa_tl \l_xeCJK_math_family_tl + { + \DeclareSymbolFont \c_xeCJK_math_tl \g_fontspec_encoding_tl + \l_xeCJK_math_family_tl \mddefault \shapedefault + \SetSymbolFont \c_xeCJK_math_tl { bold } \g_fontspec_encoding_tl + \l_xeCJK_math_family_tl \bfdefault \shapedefault + \clist_map_inline:nn { CJK, FullLeft, FullRight } + { + \clist_map_inline:cn { g_xeCJK_#1_range_clist } + { + \xeCJK_setcharclass_aux:Nn \xeCJKsetmathcode {##1} + \mathalpha \c_xeCJK_math_tl + } + } + } + } + \normalfont + } + \group_begin: + } +\xeCJK_msg_new:nn { no-CJKfamily } + { + It~seems~that~you~have~not~declare~a~CJKfamily.\\ + If~you~want~to~use~xeCJK~in~the~right~way,~you~should~use\\\\ + \token_to_str:N~\xeCJKmainfont[...]{...}\\\\ + in~the~preamble~to~declare~the~main~CJKfamily.\\ + } % \end{macrocode} % -% 缺省状态下,不允许在相邻标点中间换行。 +% 为了保证 CJK 数学字体的正确设置,应在导言区内设置 CJK 字体。 % \begin{macrocode} -\def\xeCJKallowbreakbetweenpuncts{ - \def\xeCJKpunctnobreak{ - \hskip 0pt}} - -\def\xeCJKnobreakbetweenpuncts{ - \let\xeCJKpunctnobreak\nobreak} -\xeCJKnobreakbetweenpuncts - +\@onlypreamble \setCJKmainfont +\@onlypreamble \setCJKmathfont +\@onlypreamble \setCJKsansfont +\@onlypreamble \setCJKmonofont +\@onlypreamble \setCJKromanfont % \end{macrocode} % -% 重定义\verb+\/+ +% \subsection{处理等宽字体和抄录环境} +% +% \begin{macro}[internal,var]{\g_xeCJK_monoscale_fp,\g_xeCJK_exspace_dim} % \begin{macrocode} -\let\xeCJK@itcorr\/ -\def\/{% - \relax - \ifnum\lastkern=4 % - \unkern\unkern - \fi - \xeCJK@itcorr} -\let\@@italiccorr=\/ - +\fp_new:N \g_xeCJK_monoscale_fp +\fp_gset_eq:NN \g_xeCJK_monoscale_fp \c_one_fp +\dim_new:N \g_xeCJK_exspace_dim % \end{macrocode} -% \section{标点挤压规则} +% \end{macro} +% +% \begin{macro}{\setCJKmonoscale} % \begin{macrocode} -\newcount\xeCJK@cnta -\newcount\xeCJK@cntb -\newcount\xeCJK@cntc -\newcount\xeCJK@cntd -\newcount\xeCJK@cnte -\newdimen\xeCJK@dima -\newif\ifxeCJK@dokerning - -\def\xeCJK@punctrule#1#2{ - \xdef\xeCJK@bboxname{\xeCJK@family/\f@series/\f@shape} -% \end{macrocode} -% -% 如果 punctstyle$=$plain 不作特殊处理 -% -% \begin{macrocode} - \ifcsname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @#2rule@#1\endcsname - \else - \ifcsname xeCJK@\xeCJK@bboxname @lspace@#1\endcsname - \else - {\xeCJK@setfont - \xeCJK@setpunctbounds{#1}} - \fi - \xeCJK@dokerningtrue - \ifnum\xeCJK@punctstyle=\xeCJK@ps@plain\relax - \xeCJK@dokerningfalse - \else - \ifcsname xeCJK@specialpunct#1\endcsname - \xeCJK@dokerningfalse - \fi - \fi - \ifxeCJK@dokerning - \xeCJK@cnta=\csname xeCJK@\xeCJK@bboxname @#2space@#1\endcsname\relax - \xeCJK@cntc=\xeCJK@cnta - \ifcase\xeCJK@punctstyle - % hangmobanjiao - \or % quanjiao - \or % banjiao - \advance\xeCJK@cntc -50\relax - \or % kaiming - \ifcsname xeCJK@kaiming#1\endcsname - \else - \advance\xeCJK@cntc -50\relax - \fi - \or %CCT - \advance\xeCJK@cntc -20\relax - \fi - \xeCJK@cntd=\xeCJK@cntc - \ifnum\xeCJK@cntc<0\relax - \xeCJK@cntc=0\relax - \fi - \else - \xeCJK@cnta=0\relax - \xeCJK@cntc=0\relax - \xeCJK@cntd=0\relax - \fi - \xeCJK@numtodim{\xeCJK@cnta} - \global\expandafter\edef\csname - xeCJK\xeCJK@punctstyle\xeCJK@bboxname @#2rule@#1\endcsname{ - -\xeCJK@temp em} - \xeCJK@numtodim{\xeCJK@cntc} - \global\expandafter\edef\csname - xeCJK\xeCJK@punctstyle\xeCJK@bboxname @#2glue@#1\endcsname{ - \xeCJK@temp em} - \global\expandafter\edef\csname - xeCJK\xeCJK@punctstyle\xeCJK@bboxname @#2oglue@#1\endcsname{ - \the\xeCJK@cntd} - \fi} - -\def\xeCJK@numtodim#1{ - \xeCJK@cnte=#1\relax - \ifnum\the\xeCJK@cnte<100\relax - \def\xeCJK@temp{0} - \else - \advance\xeCJK@cnte -100\relax - \def\xeCJK@temp{1} - \fi - \ifnum\the\xeCJK@cnte<10 - \edef\xeCJK@temp{\xeCJK@temp.0\the\xeCJK@cnte} - \else - \edef\xeCJK@temp{\xeCJK@temp.\the\xeCJK@cnte} - \fi} - -\expandafter\def\csname xeCJK@kaiming.\endcsname{} -\expandafter\def\csname xeCJK@kaiming。\endcsname{} -\expandafter\def\csname xeCJK@kaiming?\endcsname{} -\expandafter\def\csname xeCJK@kaiming!\endcsname{} -\expandafter\def\csname xeCJK@specialpunct—\endcsname{}% U+2014 -\expandafter\def\csname xeCJK@specialpunct─\endcsname{}% U+2500 -\expandafter\def\csname xeCJK@specialpunct…\endcsname{} -\def\xeCJK@setkern#1#2{ - \ifcsname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @kern#1#2\endcsname - \else - \xeCJK@cnta=0\relax - \ifcsname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @roglue@#1\endcsname - \advance\xeCJK@cnta\csname - xeCJK\xeCJK@punctstyle\xeCJK@bboxname @roglue@#1\endcsname - \fi - \ifcsname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @loglue@#2\endcsname - \advance\xeCJK@cnta\csname xeCJK\xeCJK@punctstyle\xeCJK@bboxname - @loglue@#2\endcsname - \fi - \relax - \ifcase\xeCJK@punctstyle - % hangmobanjiao - \or % quanjiao - \advance\xeCJK@cnta -50\relax - \or % banjiao - \or % kaiming - \ifcsname xeCJK@kaiming#1\endcsname - \ifcsname xeCJK\xeCJK@punctstyle\xeCJK@bboxname @roglue@#2\endcsname - \advance\xeCJK@cnta -50\relax - \fi - \fi - \fi - \ifnum\xeCJK@cnta<0\relax - \xeCJK@cnta=0\relax - \fi - \xeCJK@numtodim{\xeCJK@cnta} - \global\expandafter\edef\csname - xeCJK\xeCJK@punctstyle\xeCJK@bboxname @kern#1#2\endcsname{ - \xeCJK@temp em} - \fi} - +\NewDocumentCommand \setCJKmonoscale { } + { + \xeCJK_set_monoscale: + \addCJKfontfeatures { Scale = \fp_use:N \g_xeCJK_monoscale_fp } + } +\cs_new_nopar:Nn \xeCJK_set_monoscale: + { + \dim_gzero:N \g_xeCJK_exspace_dim + \group_begin: + \fontfamily \ttdefault \selectfont + \fp_gset_from_dim:Nn \g_xeCJK_monoscale_fp + { \c_two \tex_fontdimen:D \c_two \tex_font:D } + \fp_gdiv:Nn \g_xeCJK_monoscale_fp \f@size + \group_end: + } % \end{macrocode} -% 用户命令:设置两个标点之间的间距 +% \end{macro} +% +% \begin{macro}{\setCJKmonoexspace} % \begin{macrocode} -\def\xeCJKsetkern#1#2#3{ - \xdef\xeCJK@bboxname{\xeCJK@family/\f@series/\f@shape} - \global\expandafter\edef\csname - xeCJK\xeCJK@punctstyle\xeCJK@bboxname @kern#1#2\endcsname{#3}} - -\def\punctstyle#1{ - \ifcsname xeCJK@ps@#1\endcsname - \edef\xeCJK@punctstyle{\csname xeCJK@ps@#1\endcsname} - \ifnum\xeCJK@punctstyle=\xeCJK@ps@plain\relax - \xeCJKallowbreakbetweenpuncts - \fi - \else - \typeout{Warning: Punctstyle #1\space is not defined.} - \fi} - -\def\xeCJK@ps@hangmobanjiao{0} -\def\xeCJK@ps@marginkerning{0} -\def\xeCJK@ps@quanjiao{1} -\def\xeCJK@ps@fullwidth{1} -\def\xeCJK@ps@banjiao{2} -\def\xeCJK@ps@halfwidth{2} -\def\xeCJK@ps@kaiming{3} -\def\xeCJK@ps@mixedwidth{3} -\def\xeCJK@ps@CCT{4} -\def\xeCJK@ps@plain{5} -\punctstyle{quanjiao} - -\def\xeCJKplainchr{\punctstyle{plain}} - -\def\xeCJK@sidespace{10} - -\def\xeCJK@getglyphbounds#1{ - \xeCJK@cnta=\number\XeTeXglyphbounds #1 \xeCJK@gid - \xeCJK@dima 1em\relax - \xeCJK@cntb=\number\xeCJK@dima - \multiply\xeCJK@cnta 100\relax - \divide\xeCJK@cnta\xeCJK@cntb - \advance\xeCJK@cnta -15\relax - \edef\xeCJK@temp{\the\xeCJK@cnta} - \ifnum\xeCJK@temp<0\relax - \def\xeCJK@temp{0} - \fi} - - -\def\xeCJK@setpunctbounds#1{ - \edef\xeCJK@gid{\the\XeTeXcharglyph`#1} - \xeCJK@getglyphbounds{1} - \expandafter\xdef\csname xeCJK@\xeCJK@bboxname @lspace@#1\endcsname{ - \xeCJK@temp} - \xeCJK@getglyphbounds{3} - \expandafter\xdef\csname xeCJK@\xeCJK@bboxname @rspace@#1\endcsname{ - \xeCJK@temp} - \ifcsname xeCJK@specialpunct#1\endcsname - \ifx#1… - \else - \xeCJK@cnta=\number\XeTeXglyphbounds 1 \xeCJK@gid - \advance\xeCJK@cnta\number\XeTeXglyphbounds 3 \xeCJK@gid - \xeCJK@dima 1em\relax - \xeCJK@cntb=\number\xeCJK@dima - \multiply\xeCJK@cnta 100\relax - \divide\xeCJK@cnta\xeCJK@cntb - \advance\xeCJK@cnta 1\relax - \ifnum\xeCJK@cnta>9 - \edef\xeCJK@temp{-0.\the\xeCJK@cnta em} - \else - \ifnum\xeCJK@cnta>1 - \edef\xeCJK@temp{-0.0\the\xeCJK@cnta em} - \else - \edef\xeCJK@temp{-0.01 em} - \fi - \fi - \xeCJK@cnta=0 - \loop - \global\expandafter\edef\csname xeCJK\the\xeCJK@cnta\xeCJK@bboxname - @kern#1#1\endcsname{\xeCJK@temp} - \advance \xeCJK@cnta 1\relax - \ifnum\xeCJK@cnta<6\repeat - \fi - \fi} - - -\ifcsname XeTeXglyphbounds\endcsname -\else - \PackageError{xeCJK}{\string\XeTeXglyphbounds \space not defined.^^J - You have to update XeTeX to the version 0.9995.0 or later} - \relax -\fi - +\NewDocumentCommand \setCJKmonoexspace { } { \xeCJK_set_monoexspace: } +\cs_new_nopar:Nn \xeCJK_set_monoexspace: + { + \fp_gset_eq:NN \g_xeCJK_monoscale_fp \c_one_fp + \group_begin: + \fontfamily \ttdefault \selectfont + \dim_gset:Nn \g_xeCJK_exspace_dim + { \c_two \tex_fontdimen:D \c_two \tex_font:D - \f@size \p@ } + \group_end: + } % \end{macrocode} -% \section{字体设置} +% \end{macro} +% +% \begin{macro}[internal] +% { \xeCJK_fixed_ecglue:, \xeCJK_fixed_cjkglue:, \xeCJK_flexible_ecglue:, +% \xeCJK_flexible_ecglue:, \xeCJK_flexible_cjkglue: } % \begin{macrocode} -\def\CJKsymbol#1{#1} -\def\CJKpunctsymbol#1{#1} - +\cs_new_nopar:Nn \xeCJK_fixed_ecglue: { \skip_horizontal:n { .5\g_xeCJK_exspace_dim } } +\cs_new_nopar:Nn \xeCJK_fixed_cjkglue: { \skip_horizontal:N \g_xeCJK_exspace_dim } +\AtEndOfPackage + { + \tl_set_eq:NN \l_xeCJK_flexible_punctstyle_tl \l_xeCJK_punctstyle_tl + \cs_new_eq:NN \xeCJK_flexible_ecglue: \CJKecglue + \cs_new_eq:NN \xeCJK_flexible_cjkglue: \CJKglue + } % \end{macrocode} -% 设置备用字体,如果主字体没有相应的符号,将尝试使用备用字体显示。 -% \begin{macrocode} -\def\xeCJK@fallback@testsymbol#1{ - \iffontchar\font`#1 - #1 - \else - {\csname xeCJK@fallback@\xeCJK@family\endcsname #1} - \fi} +% \end{macro} +% +% \begin{macro}{\CJKfixedspacing} +% \begin{macrocode} +\NewDocumentCommand \CJKfixedspacing { } + { + \tl_if_eq:NNF \l_xeCJK_punctstyle_tl \c_xeCJK_ps_plain_tl + { + \tl_set_eq:NN \l_xeCJK_flexible_punctstyle_tl \l_xeCJK_punctstyle_tl + \punctstyle { plain } + } + \cs_if_eq:NNF \CJKecglue \xeCJK_fixed_ecglue: + { + \cs_set_eq:NN \xeCJK_flexible_ecglue: \CJKecglue + \cs_set_eq:NN \CJKecglue \xeCJK_fixed_ecglue: + } + \cs_if_eq:NNF \CJKglue \xeCJK_fixed_cjkglue: + { + \cs_set_eq:NN \xeCJK_flexible_cjkglue: \CJKglue + \cs_set_eq:NN \CJKglue \xeCJK_fixed_cjkglue: + } + } +\AtBeginDocument { \tl_put_right:Nn \verbatim@font \CJKfixedspacing } % \end{macrocode} -% |\xeCJKenablefallback| 命令打开备用字体功能,|\xeCJKdisablefallback| 命令关 -% 闭备用字体功能。此功能默认关闭。 +% \end{macro} +% +% \begin{macro}{\CJKflexiblespacing} % \begin{macrocode} -\newcommand\xeCJKenablefallback{\let\xeCJK@fallback@CJKsymbol\CJKsymbol - \def\CJKsymbol##1{\xeCJK@fallback@CJKsymbol{\xeCJK@fallback@testsymbol{##1}}}} -\newcommand\xeCJKdisablefallback{\let\CJKsymbol\xeCJK@fallback@CJKsymbol} -\ifxeCJK@fallback@ - \xeCJKenablefallback -\fi +\NewDocumentCommand \CJKflexiblespacing { m } + { + \cs_set_eq:NN \l_xeCJK_punctstyle_tl \l_xeCJK_flexible_punctstyle_tl + \cs_set_eq:NN \CJKecglue \xeCJK_flexible_ecglue: + \cs_set_eq:NN \CJKglue \xeCJK_flexible_cjkglue: + } % \end{macrocode} -% |\setCJKfallbackfamilyfont| 为 CJK 字体族设置备用字体。 +% \end{macro} +% +% \begin{macro}{\setCJKmonofont} +% 设置文档的 CJK 等宽字体族。 % \begin{macrocode} -\newcommand\setCJKfallbackfamilyfont[1]{ - \@ifnextchar[ - {\xeCJK@setfallbackfamilyfont{#1}} - {\xeCJK@setfallbackfamilyfont{#1}[]}} -\def\xeCJK@setfallbackfamilyfont#1[#2]#3{ - \expandafter\newfontfamily\csname xeCJK@fallback@#1\endcsname[#2]{#3} -} - - -\DeclareRobustCommand{\xeCJK@ULprepunctchar}[1]{ - {\XeTeXinterchartokenstate=0 - \CJKpunctsymbol{#1} - \nobreak} - \ignorespaces} -\DeclareRobustCommand{\xeCJK@ULpostpunctchar}[1]{ - {\XeTeXinterchartokenstate=0 - \CJKpunctsymbol{#1}} - \xeCJK@ignorespaces} -\def\xeCJK@ULroutines{ - \XeTeXinterchartoks 0 1 {\CJKecglue\CJKsymbol} - \XeTeXinterchartoks 4 1 {\CJKsymbol} - \XeTeXinterchartoks 5 1 {\CJKecglue\CJKsymbol} - \XeTeXinterchartoks 255 1 {\xeCJK@cclv@i} - \XeTeXinterchartoks 0 2 {\xeCJK@ULprepunctchar} - \XeTeXinterchartoks 4 2 {\xeCJK@ULprepunctchar} - \XeTeXinterchartoks 5 2 {\xeCJK@ULprepunctchar} - \XeTeXinterchartoks 255 2 {\xeCJK@ULprepunctchar} - \XeTeXinterchartoks 0 3 {\xeCJK@ULpostpunctchar} - \XeTeXinterchartoks 4 3 {\xeCJK@ULpostpunctchar} - \XeTeXinterchartoks 5 3 {\xeCJK@ULpostpunctchar} - \XeTeXinterchartoks 255 3 {\xeCJK@ULpostpunctchar}} - -\AtBeginDocument{ - \ifcsname UL@hook\endcsname - \addto@hook\UL@hook{ - \let\xeCJK@UL@CJKsymbol\CJKsymbol - \let\xeCJK@UL@CJKpunctsymbol\CJKpunctsymbol - \def\CJKsymbol#1{{\xeCJK@setfont \xeCJK@UL@CJKsymbol{#1}} - \kern -1sp\kern 1sp\xeCJK@ignorespaces} - \def\CJKpunctsymbol#1{{\xeCJK@setfont \xeCJK@UL@CJKpunctsymbol{#1}}} - \xeCJK@ULroutines} - \fi - \ifcsname ver@CJKfntef.sty\endcsname - \def\XeTeX@CJKfntef@hook{ - \xeCJK@setfont - \XeTeXinterchartokenstate=0} - \fi} - +\NewDocumentCommand \setCJKmonofont { s t+ O{} m } + { + \IfBooleanTF {#1} + { \xeCJK_set_family:nnn \CJKttdefault { Mono = Scale, #3 } {#4} } + { + \IfBooleanTF {#2} + { \xeCJK_set_family:nnn \CJKttdefault { Mono = Exspace, #3 } {#4} } + { \xeCJK_set_family:nnn \CJKttdefault {#3} {#4} } + } + } % \end{macrocode} -% |\xeCJK@setfont| 实际切换中文字体。它使用名为 -% |xeCJK@\xeCJK@family/\f@series/\f@shape/\f@size| 的宏来缓存特定 NFSS 坐标 -% 中文字体的原始 |\font| 命令格式,以加快编译速度。在第一次使用这一 NFSS 坐标 -% 时,会调用名为 |xeCJK@font@\xeCJK@family| 的宏(它将展开为 |\fontspec|), -% 利用 |fontspec| 宏包选择中文字体,并缓存原始字体形式。 -% \begin{macrocode} -\def\xeCJK@setfont{ - \ifcsname xeCJK@\xeCJK@family/\f@series/\f@shape/\f@size\endcsname +% \end{macro} +% +% \subsection{\pkg{xeCJK} 其它选项} +% +% \begin{macro}{CJKnumber,indentfirst} +% 是否启用 \pkg{CJKnumber} 宏包和首行是否缩进,其中 |CJKnumber| 选项仅 +% 在 \pkg{xeCJK} 宏包调用的时候有效。并将 \pkg{xeCJK} 中未知的选项传递给 +% \pkg{fontspec} 宏包。 +% \begin{macrocode} +\bool_new:N \g_xeCJK_indent_bool +\keys_define:nn { xeCJK / options } + { + CJKnumber .bool_set:N = \g_xeCJK_number_bool , + indentfirst .bool_set:N = \g_xeCJK_indent_bool , + normalindentfirst .meta:n = { indentfirst = true } , + quiet .code:n = + { + \msg_redirect_module:nnn { xeCJK } { warning } { info } + \msg_redirect_module:nnn { xeCJK } { info } { none } + \PassOptionsToPackage { quiet } { fontspec } + }, + silent .code:n = + { + \msg_redirect_module:nnn { xeCJK } { warning } { none } + \msg_redirect_module:nnn { xeCJK } { info } { none } + \PassOptionsToPackage { silent } { fontspec } + }, + unknown .code:n = + { + \@ifpackageloaded { fontspec } + { \xeCJK_error:nx { key-unknown } { \l_keys_key_tl } } + { \PassOptionsToPackage { \l_keys_key_tl } { fontspec } } + }, + } +\xeCJK_msg_new:nn { key-unknown } + { + Sorry,~but~\l_keys_module_tl\c_space_tl does~not~have~a~key~called~'#1'.\\\\ + The~key~'#1'~is~being~ignored. + } % \end{macrocode} -% 使用已缓存的字体。 -% \begin{macrocode} - \csname xeCJK@\xeCJK@family/\f@series/\f@shape/\f@size\endcsname - \else +% \end{macro} +% +% \subsection{\pkg{xeCJK} 初始化设置} +% +% \pkg{xeCJK} 宏包的初始化设置。 +% \begin{macrocode} +\keys_set:nn { xeCJK / options } + { + CJKglue = { \skip_horizontal:n { \c_zero_skip \@plus .08\baselineskip } } , + CJKecglue = \c_space_token , + CheckSingleglue = \CJKglue , + xCJKecglue = false , + CheckSingle = false , + CJKspace = false , + CJKmath = false , + xeCJKactive = true , + indentfirst = true , + EmboldenFactor = 4 , + SlantFactor = .167 , + PunctStyle = quanjiao , + KaiMingPunct = { . 。? ! } , + LongPunct = { — ‥ … ─ } , + MiddlePunct = { · ・ ・ } , + AllowBreakBetweenPuncts = false , + } % \end{macrocode} -% 预存需要的 NFSS 坐标到 |\xeCJK@currentcoor|,以免在缺字体时被替换字体改变。 +% +% \begin{macro}[internal]{\CJKsymbol, \CJKpunctsymbol} % \begin{macrocode} - \edef\xeCJK@currentcoor{xeCJK@\xeCJK@family/\f@series/\f@shape/\f@size} +\cs_new_nopar:Npn \CJKsymbol #1 {#1} +\cs_new_nopar:Npn \CJKpunctsymbol #1 {#1} % \end{macrocode} -% 切换未缓存的字体。 +% \end{macro} +% +% 执行宏包选项,并载入 \pkg{fontspec} 宏包。 % \begin{macrocode} - \csname xeCJK@font@\xeCJK@family\endcsname +\ProcessKeysOptions { xeCJK / options } +\RequirePackage { fontspec } [ 2011/09/13 ] % \end{macrocode} -% |\get@external@font| 可能会产生奇怪的副作用\footnote{参见 ctex-kit 项目 -% \href{http://code.google.com/p/ctex-kit/issues/detail?id=57}{issue 57}。}。 -% 这里使用分组令其局部化,仅保留对 |\external@font| 的赋值。 +% % \begin{macrocode} - \begingroup - \get@external@font - \edef\xeCJK@temp{\def\noexpand\external@font{\external@font}} - \expandafter\endgroup\xeCJK@temp +\bool_if:NT \g_xeCJK_indent_bool + { + \cs_set_eq:NN \@afterindentfalse \@afterindenttrue + \@afterindenttrue + } % \end{macrocode} -% 缓存字体。 +% +% \begin{macro}{\xeCJKsetup} +% 在导言区或文档中设置 \pkg{xeCJK} 的接口。 % \begin{macrocode} - \expandafter\global\expandafter\font - \csname\xeCJK@currentcoor\endcsname=\external@font - \fi} - -\def\CJKrmdefault{rm} -\def\setCJKmainfont{ - \xeCJK@newfontfamily{\CJKrmdefault}} - -\let\setCJKromanfont\setCJKmainfont - -\def\CJKsfdefault{sf} -\def\setCJKsansfont{ - \xeCJK@newfontfamily{\CJKsfdefault}} - -\providecommand\CJKttdefault{tt} +\NewDocumentCommand \xeCJKsetup { m } + { + \keys_set:nn { xeCJK / options } {#1} + \tex_ignorespaces:D + } % \end{macrocode} -% |\setCJKmonofont| 在后面单独定义。 +% \end{macro} +% +% \begin{macro}[internal]{\xeCJKsetemboldenfactor, \xeCJKsetslantfactor} % \begin{macrocode} - -\def\setCJKfamilyfont#1{ - \xeCJK@newfontfamily{#1}} -% \end{macrocode} -% 重定义 |\normalfont|, |\rmfamily|, |\sffamily|, |\ttfamily|,添加 CJK 字体族 -% 的设置。 -% \begin{macrocode} -\def\CJKfamilydefault{\CJKrmdefault} -\DeclareRobustCommand\normalfont - {\CJKfamily{\CJKfamilydefault} - \usefont\encodingdefault - \familydefault - \seriesdefault - \shapedefault - \relax} -\let\reset@font\normalfont - -\DeclareRobustCommand\rmfamily - {\not@math@alphabet\rmfamily\mathrm - \fontfamily\rmdefault\CJKfamily{\CJKrmdefault}\selectfont} - -\DeclareRobustCommand\sffamily - {\not@math@alphabet\sffamily\mathsf - \fontfamily\sfdefault\CJKfamily{\CJKsfdefault}\selectfont} - -\DeclareRobustCommand\ttfamily - {\not@math@alphabet\ttfamily\mathtt - \fontfamily\ttdefault\CJKfamily{\CJKttdefault}\selectfont} - +\NewDocumentCommand \xeCJKsetEmboldenFactor { m } + { \xeCJKsetup { EmboldenFactor = {#1} } } +\NewDocumentCommand \xeCJKsetSlantFactor { m } + { \xeCJKsetup { SlantFactor = {#1} } } % \end{macrocode} -% \string\xeCJK@newfontfamily is similar to \string\newfontfamily -% but introduce fake slant/bold fonts for CJK characters. +% \end{macro} +% +% \begin{macro}[internal]{\punctstyle, \xeCJKplainchr} % \begin{macrocode} -\newcommand*\xeCJK@newfontfamily[1]{ - \@ifnextchar[ - {\xeCJK@newfontfamily@{#1}} - {\xeCJK@newfontfamily@{#1}[]}} - -\def\xeCJK@setmacro@define@key#1{ - \define@key[xeCJK]{preparse}{#1}{ - \expandafter\xdef\csname xeCJK@#1\endcsname{##1}}} - -\xeCJK@setmacro@define@key{ItalicFont} -\xeCJK@setmacro@define@key{BoldFont} -\xeCJK@setmacro@define@key{BoldItalicFont} - -\def\xeCJK@newfontfamily@#1[#2]#3{ - % - % Get user defined options - - \let\xeCJK@BoldFont\@empty - \let\xeCJK@ItalicFont\@empty - \let\xeCJK@BoldItalicFont\@empty - \bgroup - \setkeys*[xeCJK]{preparse}{#2} - \egroup - \edef\xeCJK@Features{} - - \ifxeCJK@BoldFont@ - \ifx\xeCJK@BoldFont\@empty - \edef\xeCJK@Features{BoldFont={#3}, - BoldFeatures={RawFeature={embolden=\xeCJK@emboldenfactor}}} - \fi - \fi - - \ifxeCJK@SlantFont@ - \ifx\xeCJK@ItalicFont\@empty - \ifx\xeCJK@Features\@empty - \edef\xeCJK@Features{ItalicFont={#3}, - ItalicFeatures={RawFeature={slant=\xeCJK@slantfactor}}} - \else - \edef\xeCJK@Features{\xeCJK@Features,ItalicFont={#3}, - ItalicFeatures={RawFeature={slant=\xeCJK@slantfactor}}} - \fi - \fi - - \ifx\xeCJK@BoldItalicFont\@empty - \ifx\xeCJK@BoldFont\@empty - \edef\xeCJK@Features{\xeCJK@Features,BoldItalicFont={#3}, - BoldItalicFeatures={RawFeature={embolden=\xeCJK@emboldenfactor,slant=\xeCJK@slantfactor}}} - \else - \edef\xeCJK@Features{\xeCJK@Features,BoldItalicFont={\xeCJK@BoldFont}, - BoldItalicFeatures={RawFeature={slant=\xeCJK@slantfactor}}} - \fi - \fi - \fi - - \edef\xeCJK@temp{#2} - \ifx\xeCJK@temp\@empty - \else - \ifx\xeCJK@Features\@empty - \edef\xeCJK@Features{#2} - \else - \edef\xeCJK@Features{\xeCJK@Features,#2} - \fi - \fi - - \expandafter\edef\csname xeCJK@font@#1\endcsname{ - \noexpand\fontspec[\xeCJK@Features]{#3}} - \expandafter\edef\csname xeCJK@fontoptions@#1\endcsname{\xeCJK@Features} - \expandafter\edef\csname xeCJK@fontname@#1\endcsname{#3}} - +\NewDocumentCommand \punctstyle { m } { \xeCJKsetup { PunctStyle = {#1} } } +\cs_new_nopar:Npn \xeCJKplainchr { \punctstyle { plain } } % \end{macrocode} -% Redefine \verb+\addfontfeatures+ +% \end{macro} +% +% \begin{macro}[internal]{\CJKsetecglue} % \begin{macrocode} - -\newcount\xeCJK@featureadded -\xeCJK@featureadded=0 - -\let\xeCJK@addfontfeatures\addfontfeatures -\def\addCJKfontfeatures#1{ - \global\advance\xeCJK@featureadded\@ne - \ifcsname xeCJK@family\endcsname - \edef\xeCJK@tempa{\csname xeCJK@fontoptions@\xeCJK@family\endcsname,#1} - \edef\xeCJK@tempb{\csname xeCJK@fontname@\xeCJK@family\endcsname} - \edef\xeCJK@tempf{\xeCJK@family @\the\xeCJK@featureadded} - \expandafter\edef\csname xeCJK@font@\xeCJK@tempf\endcsname{ - \noexpand\fontspec[\xeCJK@tempa]{\xeCJK@tempb}} - \expandafter\edef\csname xeCJK@fontoptions@\xeCJK@tempf\endcsname{\xeCJK@tempa} - \expandafter\edef\csname xeCJK@fontname@\xeCJK@tempf\endcsname{\xeCJK@tempb} - \CJKfamily{\xeCJK@tempf} - \fi} - -\def\addfontfeatures#1{ - \xeCJK@addfontfeatures{#1} - \addCJKfontfeatures{#1}} - -% redefine \verb+\CJKfamily+ - -\expandafter\def\csname xeCJK@font@\CJKfamilydefault\endcsname{} - -\DeclareRobustCommand\CJKfamily[1]{ - \ifcsname xeCJK@font@#1\endcsname - \edef\xeCJK@family{#1} - \else - \ifcsname xeCJK@#1@warned\endcsname - \else - \PackageWarning{xeCJK}{ - Unknown CJK family `#1' is ignored.^^J - Use \string\setCJKfamilyfont \space to define a CJK family.} - \expandafter\gdef\csname xeCJK@#1@warned\endcsname{} - \fi - \fi} -\AtBeginDocument{\CJKfamily{\CJKfamilydefault}} - -\def\xeCJKsetslantfactor#1{\edef\xeCJK@slantfactor{#1}} -\def\xeCJKsetemboldenfactor#1{\edef\xeCJK@emboldenfactor{#1}} - -\xeCJKsetslantfactor{0.17} -\xeCJKsetemboldenfactor{4} +\NewDocumentCommand \CJKsetecglue { m } { \xeCJKsetup { CJKecglue = {#1} } } +\cs_new_eq:NN \xeCJKsetecglue \CJKsetecglue % \end{macrocode} -% \section{处理等宽字体和抄录环境} +% \end{macro} +% +% \subsection{兼容性修补} +% +% \begin{macro}[internal]{\/} +% 修复倾斜校正。 % \begin{macrocode} -\ExplSyntaxOn - -\fp_new:N \g_xecjk_monoscale_fp -\fp_gset_eq:NN \g_xecjk_monoscale_fp \c_one_fp - -\dim_new:N \g_xecjk_exspace_dim -\dim_gset_eq:NN \g_xecjk_exspace_dim \c_zero_dim - -\cs_new:Nn \xecjk_setmonoscale: -{ - \dim_gset_eq:NN \g_xecjk_exspace_dim \c_zero_dim - \group_begin: - \fontfamily\ttdefault\selectfont - \fp_gset_from_dim:Nn \g_xecjk_monoscale_fp {\c_two\fontdimen\c_two\font} - \fp_gdiv:Nn \g_xecjk_monoscale_fp {\f@size} - \group_end: -} - -\newcommand*\setCJKmonoscale{ - \xecjk_setmonoscale: - \addCJKfontfeatures{Scale=\fp_use:N\g_xecjk_monoscale_fp} -} - -\DeclareRobustCommand\setCJKmonoscalefont[2][]{ - \xecjk_setmonoscale: - \xeCJK@newfontfamily{\CJKttdefault}[#1,Scale=\fp_use:N \g_xecjk_monoscale_fp]{#2}} - -\cs_new:Nn \xecjk_set_monoexspace: -{ - \fp_gset_eq:NN \g_xecjk_monoscale_fp \c_one_fp - \group_begin: - \fontfamily\ttdefault\selectfont - \dim_gset:Nn \g_xecjk_exspace_dim {\c_two\fontdimen\c_two\font - \f@size\p@} - \group_end: -} - -\newcommand*\setCJKmonoexspace{ - \xecjk_set_monoexspace: -} - -\cs_new:Nn \xecjk_fixed_ecglue: -{ - \skip_horizontal:N .5\g_xecjk_exspace_dim -} - -\cs_new:Nn \xecjk_fixed_cjkglue: -{ - \skip_horizontal:N \g_xecjk_exspace_dim -} - -\tl_set_eq:NN \l_xecjk_flexible_punctstyle_tl \xeCJK@punctstyle -\cs_set_eq:NN \xecjk_flexible_ecglue: \CJKecglue -\cs_set_eq:NN \xecjk_flexible_cjkglue: \CJKglue - -\newcommand*\CJKfixedspacing{ - \unless\ifnum \xeCJK@punctstyle = \xeCJK@ps@plain - \tl_set_eq:NN \l_xecjk_flexible_punctstyle_tl \xeCJK@punctstyle - \punctstyle{plain} - \fi - \unless\ifx \CJKecglue \xecjk_fixed_ecglue: - \cs_set_eq:NN \xecjk_flexible_ecglue: \CJKecglue - \let \CJKecglue \xecjk_fixed_ecglue: - \fi - \unless\ifx \CJKglue \xecjk_fixed_cjkglue: - \cs_set_eq:NN \xecjk_flexible_cjkglue: \CJKglue - \let \CJKglue \xecjk_fixed_cjkglue: - \fi -} - -\newcommand*\CJKflexiblespacing{ - \let \xeCJK@punctstyle \l_xecjk_flexible_punctstyle_tl - \let \CJKecglue \xecjk_flexible_ecglue: - \let \cjkglue \xecjk_flexible_cjkglue: -} - -\DeclareRobustCommand\setCJKmonoexspacefont[2][]{ - \xecjk_set_monoexspace: - \xeCJK@newfontfamily{\CJKttdefault}[#1]{#2}} - -\def\xeCJK@ifplus#1{\@ifnextchar +{\@firstoftwo{#1}}} - -\DeclareRobustCommand\setCJKmonofont{\@ifstar - {\setCJKmonoscalefont} - {\xeCJK@ifplus - {\setCJKmonoexspacefont} - {\xeCJK@newfontfamily{\CJKttdefault}}}} - +\cs_new_eq:NN \xeCJK_itcorr_aux \/ +\bool_new:N \g_xeCJK_itcorr_bool +\cs_set_protected_nopar:Npn \/ + { + \scan_stop: + \int_compare:nNnT \tex_lastkern:D = \c_three + { + \tex_unkern:D \tex_unkern:D + \bool_gset_true:N \g_xeCJK_itcorr_bool + } + \xeCJK_itcorr_aux + } +\cs_set_eq:NN \@@italiccorr \/ +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\xeCJK_compatibility_hook:,\xeCJK_set_others_toks:n,\xeCJK_Others_class} +% 简单处理与同样使用 |\XeTeXinterchartoks| 机制的宏包的兼容问题。 +% \begin{macrocode} +\cs_new_nopar:Nn \xeCJK_compatibility_hook: + { + \int_compare:nNnF + { \c_three + \seq_length:N \g_xeCJK_class_seq } = \xe@alloc@intercharclass + { + \int_set_eq:NN \l_tmpa_int \c_three + \int_until_do:nNnn \l_tmpa_int = \xe@alloc@intercharclass + { + \int_incr:N \l_tmpa_int + \seq_if_in:NVF \g_xeCJK_class_seq \l_tmpa_int + { \xeCJK_set_others_toks:n \l_tmpa_int } + } + } + } +\cs_new_nopar:Nn \xeCJK_set_others_toks:n + { + \int_set:Nn \xeCJK_Others_class {#1} + \clist_map_inline:Nn \g_xeCJK_CJK_class_clist + { + \xeCJK_copy_inter_class_toks:nnnn {##1} { Others } {##1} { NormalSpace } + \xeCJK_copy_inter_class_toks:nnnn { Others } {##1} { NormalSpace } {##1} + \exp_args:Nnnx \xeCJK_app_inter_class_toks:nnn {##1} { Others } + { \xeCJK_get_inter_class_toks:nn { Default } { Others } } + \exp_args:Nnnx \xeCJK_pre_inter_class_toks:nnn { Others } {##1} + { \xeCJK_get_inter_class_toks:nn { Others } { Default } } + \tl_if_empty:xT { \xeCJK_get_inter_class_toks:nn { Others } { Boundary } } + { + \xeCJK_copy_inter_class_toks:nnnn + { Others } { Boundary } { Default } { Boundary } + } + \tl_if_empty:xT { \xeCJK_get_inter_class_toks:nn { Boundary } { Others } } + { + \xeCJK_copy_inter_class_toks:nnnn + { Boundary } { Others } { Boundary } { Default } + } + } + } +\int_new:N \xeCJK_Others_class +\tl_put_right:Nn \document { \xeCJK_compatibility_hook: \tex_ignorespaces:D } % \end{macrocode} -% 修补 \verbatim@font +% \end{macro} +% +% \begin{macro}[internal]{\xeCJK_patch:Nnn} +% 给已有宏内容前后附加补丁。 % \begin{macrocode} -\AtBeginDocument{ - \tl_put_right:Nn \verbatim@font { - \CJKfixedspacing +\cs_new_nopar:Nn \xeCJK_patch:Nnn + { \tl_put_left:Nn #1 {#2} \tl_put_right:Nn #1 {#3} } +% \end{macrocode} +% \end{macro} +% +% 单独处理宽度有分歧的几个标点:包括省略号、破折号、间隔号、引号等中西文混用的 +% 符号, 保证其命令形式输出的是西文字体。并对一些编码的符号宏包做特殊处理。 +% \begin{macrocode} +\AtBeginDocument + { + \tl_map_inline:nn + { + \textellipsis \textemdash \textperiodcentered \textcentereddot + \textquoteleft \textquoteright \textquotedblleft \textquotedblright + } + { \xeCJK_patch:Nnn #1 { \group_begin: \makexeCJKinactive } { \group_end: } } + \xeCJK_patch:Nnn \tipaencoding { \makexeCJKinactive } { } + \cs_set_eq:NN \xeCJK_aux_r \r + \cs_set_nopar:Npn \r #1 { { \makexeCJKinactive \xeCJK_aux_r {#1} } } + \@ifpackageloaded { pifont } + { + \RenewDocumentCommand \Pifont { m } + { + \fontencoding {U} \fontfamily {#1} \fontseries {m} \fontshape {n} + \selectfont \makexeCJKinactive + } + } { } } -} - -\ExplSyntaxOff - % \end{macrocode} -% \section{使用CJKnumb宏包} -% \begin{macrocode} % - - -\ifxeCJK@num - \edef\CJK@UnicodeEnc{UTF8} - \def\CJKaddEncHook#1#2{\expandafter\def\csname xeCJK@enc@#1\endcsname{#2}} - \def\Unicode#1#2{\@tempcnta #1\relax - \multiply\@tempcnta 256\relax - \advance\@tempcnta #2\relax - \char\@tempcnta} - \RequirePackage{CJKnumb} - \csname xeCJK@enc@UTF8\endcsname - \def\CJK@tenthousand{万} -\fi +% 禁止在 \pkg{xeCJK} 宏包后再载入 \pkg{CJK} 宏包。 +% \begin{macrocode} +\tl_set:cn { ver@CJK.sty } { 2050/01/01 } % \end{macrocode} -% 可以使用CJK包中的cpx或cp文件。 +% +% \begin{macro}[internal]{\xeCJKcaption} +% 可以使用 \pkg{CJK} 宏包中的 |.cpx| 文件。 % \begin{macrocode} - -\def\CJK@ifundefined#1{ - \ifx #1\@undefined - \expandafter\@firstoftwo - \else - \expandafter\@secondoftwo - \fi -} - -\newcommand{\xeCJKcaption}[2][]{ - \edef\xeCJK@temp{#1} - \ifx\xeCJK@temp\@empty - \else - \XeTeXdefaultencoding "#1" - \fi - \makeatletter - \input{#2.cpx} - \makeatother - \XeTeXdefaultencoding "UTF-8"} - -\endlinechar `\^^M -\catcode "FEFF=9\relax +\cs_if_free:NT \CJK@ifundefined + { \cs_set_eq:NN \CJK@ifundefined \cs_if_free:NTF } +\NewDocumentCommand \xeCJKcaption { o m } + { + \IfValueT {#1} { \XeTeXdefaultencoding "#1" } + \cs_set_nopar:Nx \xeCJK_reset_at_catcode: + { + \exp_not:n { \char_set_catcode:nn { `\@ } } + { \char_value_catcode:n { `\@ } } + } + \char_set_catcode_letter:N \@ + \file_input:n { #2.cpx } + \xeCJK_reset_at_catcode: + \XeTeXdefaultencoding "UTF-8" + } % \end{macrocode} +% \end{macro} % +% \begin{macro}[internal] +% {\xeCJK_ULprepunctchar:n, \xeCJK_ULpostpunctchar:n, \xeCJK_ULroutines:} +% \begin{macrocode} +\cs_new_protected_nopar:Nn \xeCJK_ULprepunctchar:n + { + { \makexeCJKinactive \CJKpunctsymbol {#1} \nobreak } + \tex_ignorespaces:D + } +\cs_new_protected_nopar:Nn \xeCJK_ULpostpunctchar:n + { + { \makexeCJKinactive \CJKpunctsymbol {#1} } + \xeCJK_ignorespaces: + } +\cs_new_protected_nopar:Nn \xeCJK_ULroutines: + { + \xeCJK_inter_class_toks:nnn { Default } { CJK } { \CJKecglue \CJKsymbol } + \xeCJK_inter_class_toks:nnn { HalfLeft } { CJK } { \CJKsymbol } + \xeCJK_inter_class_toks:nnn { HalfRight } { CJK } { \CJKecglue \CJKsymbol } + \xeCJK_inter_class_toks:nnn { Boundary } { CJK } { \xeCJK_Boundary_and_CJK: } + \clist_map_inline:nn { Default, HalfLeft, HalfRight, Boundary } + { + \xeCJK_inter_class_toks:nnn {##1} { FullLeft } { \xeCJK_ULprepunctchar:n } + \xeCJK_inter_class_toks:nnn {##1} { FullRight } { \xeCJK_ULpostpunctchar:n } + } + \xeCJK_UL_subclass_patch_tl + } +% \end{macrocode} +% \end{macro} +% +% 对 \pkg{ulem} 宏包打补丁,以支持 \pkg{CJKfntef} 宏包。 +% \begin{macrocode} +\AtBeginDocument + { + \cs_if_exist:NT \UL@hook + { + \addto@hook \UL@hook + { + \cs_set_eq:NN \xeCJK_UL_CJKsymbol \CJKsymbol + \cs_set_eq:NN \xeCJK_UL_CJKpunctsymbol \CJKpunctsymbol + \cs_set_nopar:Npn \CJKsymbol #1 + { + { \xeCJK_select_font: \xeCJK_UL_CJKsymbol {#1} } + \xeCJK_CJK_kern: \xeCJK_ignorespaces: + } + \cs_set_nopar:Npn \CJKpunctsymbol #1 + { { \xeCJK_select_font: \xeCJK_UL_CJKpunctsymbol {#1} } } + \xeCJK_ULroutines: + } + } + \cs_if_exist:NT \XeTeX@CJKfntef@hook + { + \cs_set_nopar:Npn \XeTeX@CJKfntef@hook + { \xeCJK_select_font: \makexeCJKinactive } + } + } +% \end{macrocode} % +% 使用 \pkg{CJKnumb} 宏包。 +% \begin{macrocode} +\bool_if:NT \g_xeCJK_number_bool + { + \tl_set:Nn \CJK@UnicodeEnc { UTF8 } + \cs_set_nopar:Npn \CJKaddEncHook #1#2 { \cs_set_nopar:cpn { xeCJK_enc_#1 } {#2} } + \cs_set_nopar:Npn \Unicode #1#2 + { \tex_char:D \int_eval:n { #1 * \c_two_hundred_fifty_six + #2 } } + \RequirePackage { CJKnumb } + \use:c { xeCJK_enc_\CJK@UnicodeEnc } + \tl_set:Nn \CJK@tenthousand { 万 } + \tl_set:Nn \CJK@hundredmillion { 亿 } + } +% \end{macrocode} % -% \iffalse -%</xeCJK> +% \begin{macrocode} +%</package> +% \end{macrocode} % +% \section{例子} % -%<*example-addspaces> -% \fi +% \subsection{\pkg{example-autofake.tex}} % -% \clearpage -% \part{example-addspaces.tex} % \begin{macrocode} +%<*ex-autofake> +% \end{macrocode} +% +% \begin{macrocode} \documentclass{article} -\usepackage[boldfont,slantfont]{xeCJK} -\usepackage{xcolor} -\setCJKmainfont{AR PLBaosong2GBK Light} -\textwidth 190mm -\oddsidemargin 0pt +\usepackage[AutoFakeBold,AutoFakeSlant]{xeCJK} +\setCJKmainfont[BoldFont=simhei.ttf, ItalicFont=simkai.ttf]{simsun.ttc} +\setCJKsansfont[AutoFakeSlant=false, + BoldFont=simhei.ttf, ItalicFont=simkai.ttf]{simsun.ttc} +\setCJKmonofont[ItalicFont=simkai.ttf]{simsun.ttc} \begin{document} -\baselineskip 18pt -\parskip 10pt -\parindent 0em - -{\slshape 斜体 Slanted \bfseries 斜体 Slanted} - - -\long\def\sometexts{\par{\color{\colora} - 这是 English 中文 {\itshape Chinese} 中文 \LaTeX\ - 间隔 \textit{Italic} 中文\textbf{字体} a 数学 $b$ 数学 $c$ $d$ -\\ - 这是English中文{\itshape Chinese}中文\LaTeX\ - 间隔\textit{Italic}中文\textbf{字体}a数学$b$数学$c$ $d$\\ -This is an example. 这是一个例子 -}} - -\def\colora{blue} -\CJKsetecglue{\hskip 0.15em plus 0.05em minus 0.05em} -\verb+\CJKsetecglue{\hskip 0.15em plus 0.05em minus 0.05em}+ -\sometexts - -\def\colora{red} -\CJKsetecglue{ } -\verb+\CJKsetecglue{ }+ -\sometexts - - -{\verb+\CJKspace+ - -\CJKspace -这 是 一行 文字。} - -{\verb+\CJKnospace+ - -\CJKnospace -这 是 一行 文字。} - +\centering +\begin{tabular}{lllll} +\hline + {\bf rm} & md & up & \verb|\rmfamily\mdseries\upshape| & + {\rmfamily\mdseries\upshape English 中文字体} \\ + & md & it & \verb|\rmfamily\mdseries\itshape| & + {\rmfamily\mdseries\itshape English 中文字体} \\ + & md & sl & \verb|\rmfamily\mdseries\slshape| & + {\rmfamily\mdseries\slshape English 中文字体} \\ \cline{2-5} + & bf & up & \verb|\rmfamily\bfseries\upshape| & + {\rmfamily\bfseries\upshape English 中文字体} \\ + & bf & it & \verb|\rmfamily\bfseries\itshape| & + {\rmfamily\bfseries\itshape English 中文字体} \\ + & bf & sl & \verb|\rmfamily\bfseries\slshape| & + {\rmfamily\bfseries\slshape English 中文字体} \\ \hline + {\bf sf} & md & up & \verb|\sffamily\mdseries\upshape| & + {\sffamily\mdseries\upshape English 中文字体} \\ + & md & it & \verb|\sffamily\mdseries\itshape| & + {\sffamily\mdseries\itshape English 中文字体} \\ + & md & sl & \verb|\sffamily\mdseries\slshape| & + {\sffamily\mdseries\slshape English 中文字体} \\ \cline{2-5} + & bf & up & \verb|\sffamily\bfseries\upshape| & + {\sffamily\bfseries\upshape English 中文字体} \\ + & bf & it & \verb|\sffamily\bfseries\itshape| & + {\sffamily\bfseries\itshape English 中文字体} \\ + & bf & sl & \verb|\sffamily\bfseries\slshape| & + {\sffamily\bfseries\slshape English 中文字体} \\ \hline + {\bf tt} & md & up & \verb|\ttfamily\mdseries\upshape| & + {\ttfamily\mdseries\upshape English 中文字体} \\ + & md & it & \verb|\ttfamily\mdseries\itshape| & + {\ttfamily\mdseries\itshape English 中文字体} \\ + & md & sl & \verb|\ttfamily\mdseries\slshape| & + {\ttfamily\mdseries\slshape English 中文字体} \\ \cline{2-5} + & bf & up & \verb|\ttfamily\bfseries\upshape| & + {\ttfamily\bfseries\upshape English 中文字体} \\ + & bf & it & \verb|\ttfamily\bfseries\itshape| & + {\ttfamily\bfseries\itshape English 中文字体} \\ + & bf & sl & \verb|\ttfamily\bfseries\slshape| & + {\ttfamily\bfseries\slshape English 中文字体} \\ \hline +\end{tabular} \end{document} - % \end{macrocode} -% \iffalse -%</example-addspaces> -%<*example-CJKchecksingle> -% \fi % -% \clearpage -% \part{example-CJKchecksingle.tex} % \begin{macrocode} -\documentclass{article} -\usepackage[CJKchecksingle]{xeCJK} -\setCJKmainfont{AR PLBaosong2GBK Light} -\textwidth 120mm -\oddsidemargin 0pt -\def\usemacro#1{\csname#1\endcsname $\backslash$#1} -\begin{document} -\baselineskip 18pt -\parskip 10pt -\parindent 0em - -\long\def\sometexts{xeCJK 改进了中英文间距的处理,并可以避免单个汉字独占一段的最后一行。 - -xeCJK 改进了中英文间距的处理,并且可以避免单个汉字独占一段的最后一行。 - -xeCJK 改进了中英文间距的处理, 并且还可以避免单个汉字独占一段的最后一行. - -} - -\sometexts -\vskip 20mm - -不用CJKchecksingle的效果: - -\makeatletter -\def\xeCJK@i@i{\CJKglue\CJKsymbol} -\sometexts -\end{document} - +%</ex-autofake> % \end{macrocode} -% \iffalse -%</example-CJKchecksingle> -%<*example-CJKfntef> -% \fi % -% \clearpage -% \part{example-CJKfntef.tex} +% \subsection{\pkg{example-fallback.tex}} +% % \begin{macrocode} - -\documentclass[11pt]{article} -\textheight 220mm -\textwidth 150mm -\oddsidemargin 0pt -\evensidemargin 0pt -\usepackage[boldfont]{xeCJK} -\usepackage{xcolor} +%<*ex-fallback> +% \end{macrocode} +% +% \begin{macrocode} +\documentclass{article} +\usepackage[AutoFallBack]{xeCJK} \usepackage{CJKfntef} - +\usepackage{array} +\setCJKmainfont[AutoFakeBold,AutoFakeSlant]{KaiTi_GB2312} +\setCJKfallbackfamilyfont{\CJKrmdefault}[BoldFont=SimHei] + { [SlantedFont=FangSong]{SimSun} , + [BoldFont=*] {SimSun-ExtB} } \begin{document} -\setCJKmainfont{AR PLBaosong2GBK Light}% 设置缺省中文字体 -\setCJKmonofont*{AR PLBaosong2GBK Light}% 设置等宽中文字体,令其与英文对齐 - -\baselineskip 16pt -\parindent 2em - -\section{举例} -\begin{verbatim} -抄录环境中,标点不会被“压缩”。 -Alignment with English characters. -\end{verbatim} - -\CJKunderline{汉字}\CJKunderline{加下划线加下划线加下划线加下划线 -加下划线加下划线加下划线加下划线加下划线加下划线加下划线} - -\CJKunderwave{波浪线} +漢字源𣴑考 -\ifcsname CJKunderanyline\endcsname - \CJKunderanyline{0.5em}{\sixly \kern-.021em\char58 \kern-.021em}{自定义下划线} +\textbf{漢字源𣴑考} - \CJKunderanyline{0.2em}{\kern-.03em\vtop{\kern.2ex\hrule width.2em\kern 0.11em - \hrule height .1em}\kern-.03em}{自定义下划线} +\textsl{漢字源𣴑考} - \CJKunderanysymbol{0.2em}{$\cdot$}{汉字加点} -\fi +\CJKunderwave{漢字源𣴑考} +\begin{table}[ht] +\caption{生僻字测试} +\medskip\centering +\begin{tabular}{*4{|c>{\ttfamily U+}l}|} +㐀 & 3400 & 㐁 & 3401 & 㐂 & 3402 & 㐃 & 3403 \\ +㐄 & 3404 & 㐅 & 3405 & 㐆 & 3406 & 㐇 & 3407 \\ +㐈 & 3408 & 㐉 & 3409 & 㐊 & 340A & 㐋 & 340B \\ +㐌 & 340C & 㐍 & 340D & 㐎 & 340E & 㐏 & 341F \\ +㐐 & 3410 & 㐑 & 3411 & 㐒 & 3412 & 㐓 & 3413 \\ +㐔 & 3414 & 㐕 & 3415 & 㐖 & 3416 & 㐗 & 3417 \\ +㐘 & 3418 & 㐙 & 3419 & 㐚 & 341A & 㐛 & 341B \\ +㐜 & 341C & 㐝 & 341D & 㐞 & 341E & 㐟 & 341F \\[1ex] +𠀀 & 20000 & 𠀁 & 20001 & 𠀂 & 20002 & 𠀃 & 20003 \\ +𠀄 & 20004 & 𠀅 & 20005 & 𠀆 & 20006 & 𠀇 & 20007 \\ +𠀈 & 20008 & 𠀉 & 20009 & 𠀊 & 2000A & 𠀋 & 2000B \\ +𠀌 & 2000C & 𠀍 & 2000D & 𠀎 & 2000E & 𠀏 & 2000F \\ +𠀐 & 20010 & 𠀑 & 20011 & 𠀒 & 20012 & 𠀓 & 20013 \\ +𠀔 & 20014 & 𠀕 & 20015 & 𠀖 & 20016 & 𠀗 & 20017 \\ +𠀘 & 20018 & 𠀙 & 20019 & 𠀚 & 2001A & 𠀛 & 2001B \\ +𠀜 & 2001C & 𠀝 & 2001D & 𠀞 & 2001E & 𠀟 & 2001F \\ +\end{tabular} +\end{table} \end{document} % \end{macrocode} -% \iffalse -%</example-CJKfntef> -%<*example-fallback> -% \fi -% \part{example-fallback.tex} -% \setCJKfallbackfamilyfont{\CJKrmdefault}{SimSun-ExtB} -% \xeCJKenablefallback +% +% \begin{macrocode} +%</ex-fallback> +% \end{macrocode} +% +% \subsection{\pkg{example-SubCJKBlock.tex}} +% % \begin{macrocode} +%<*ex-block> +% \end{macrocode} +% +% \begin{macrocode} \documentclass{article} -\usepackage[fallback]{xeCJK} -\usepackage{CJKfntef} -\setCJKmainfont{SimSun} -\setCJKfallbackfamilyfont{\CJKrmdefault}{SimSun-ExtB} +\usepackage{xeCJK} +\usepackage{array} +\xeCJKDeclareSubCJKBlock{Ext-A} { "3400 -> "4DBF } +\xeCJKDeclareSubCJKBlock{Ext-B} { "20000 -> "2A6DF } +\xeCJKDeclareSubCJKBlock{Kana} { "3040 -> "309F, "30A0 -> "30FF, "31F0 -> "31FF, } +\xeCJKDeclareSubCJKBlock{Hangul}{ "1100 -> "11FF, "3130 -> "318F, "A960 -> "A97F, "AC00 -> "D7AF } +\setCJKmainfont[Ext-A=SimHei,Ext-B=SimSun-ExtB]{SimSun} +\setCJKmainfont[Kana]{Meiryo} +\setCJKmainfont[Hangul]{Malgun Gothic} +\parindent=2em \begin{document} +\long\def\showtext{% +中日韩越统一表意文字(英语:CJKV Unified Ideographs),旧称中日韩统一表意文字(英语:CJK Unified Ideographs),也称统一汉字(英语:Unihan),目的是要把分别来自中文、日文、韩文、越文、壮文中,对于相同起源、本义相同、形状一样或稍异的表意文字(主要为汉字,但也有仿汉字如:方块壮字、日文汉字(かんじ / kanji)、韩文汉字(한자 / hanja)、越南的喃字(Chữ Nôm)与越文汉字(Chữ Nho,在越南也称作儒字),应赋予其在ISO 10646及统一码标准中有相同编码。此计划原本只包含中文、日文及韩文中所使用的汉字,是以旧称中日韩统一表意文字(CJK)。后来,此计划加入了越文的喃字,所以合称中日韩越统一表意文字(CJKV)。 -漢字源𣴑考 +CJK統合漢字(シージェーケーとうごうかんじ、CJK Unified Ideographs)は、ISO/IEC 10646 (Universal Multiple-Octet Coded Character Set, 略称 UCS) および Unicodeにて採用されている符号化用漢字集合およびその符号表である。CJK統合漢字の名称は、中国語(Chinese)、日本語(Japanese)、韓国語(Korean)で使われている漢字をひとまとめにしたことからきている。CJK統合漢字の初版である Unified Repertoire and Ordering (URO) 第二版は1992年に制定されたが、1994年にベトナムで使われていた漢字も含めることにしたため、CJKVと呼ばれる事もある。CJKVは、中国語・日本語・韓国語・ベトナム語 (英語: Chinese-Japanese-Korean-Vietnamese) の略。特に、その4言語で共通して使われる、または使われていた文字体系である漢字(チュノムを含む)のこと。ソフトウェアの国際化、中でも文字コードに関する分野で用いられる。 -\CJKunderwave{漢字源𣴑考} +\CJKspace +한중일월 통합 한자(또는 한중일 통합 한자)는 유니코드에 담겨 있는 한자들의 집합으로, 한국, 중국, 일본에서 쓰이는 한자를 묶은 것이기 때문에 머리 글자를 따서 한중일(CJK) 통합 한자라고 불렀는데, 최근에는 베트남에서 쓰이는 한자도 추가되었기에 한중일월(CJKV) 통합 한자로 부르게 되었다. + +처음에 유니코드에는 65,536($=2^{16}$)자만 들어갈 수 있었기 때문에, 가장 많은 문자가 배당되는 한자를 위해서 한국, 중국, 일본에서 사용하는 한자 중에 모양이 유사하며 그 뜻이 같은 글자를 같은 코드로 통합했다. 따라서 문자 코드만으로 그 한자가 사용되는 언어를 알아 낼 수 없는데, 다만 중국의 간체자나 번체자, 일본의 구자체나 신자체 등 분명하게 모양이 다른 글자는 별도의 부호를 할당하고 있다. 이런 문자 할당 정책에 반발하여 TRON과 같은 인코딩이 만들어지기도 했으나, 실제로 통합된 한자의 차이가 별로 크지 않기 때문에 문제가 되지 않는다는 의견도 있다. +\CJKnospace} +\showtext + +\bigskip +\xeCJKCancelSubCJKBlock{Kana,Hangul} +\showtext + +\bigskip +\xeCJKRestoreSubCJKBlock{Hangul} +\showtext \begin{table}[ht] \caption{生僻字测试} -\centering -\begin{tabular}{|cc|cc|cc|cc|} +\medskip\centering +\begin{tabular}{*4{|c>{\ttfamily U+}l}|} +㐀 & 3400 & 㐁 & 3401 & 㐂 & 3402 & 㐃 & 3403 \\ +㐄 & 3404 & 㐅 & 3405 & 㐆 & 3406 & 㐇 & 3407 \\ +㐈 & 3408 & 㐉 & 3409 & 㐊 & 340A & 㐋 & 340B \\ +㐌 & 340C & 㐍 & 340D & 㐎 & 340E & 㐏 & 341F \\ +㐐 & 3410 & 㐑 & 3411 & 㐒 & 3412 & 㐓 & 3413 \\ +㐔 & 3414 & 㐕 & 3415 & 㐖 & 3416 & 㐗 & 3417 \\ +㐘 & 3418 & 㐙 & 3419 & 㐚 & 341A & 㐛 & 341B \\ +㐜 & 341C & 㐝 & 341D & 㐞 & 341E & 㐟 & 341F \\[1ex] 𠀀 & 20000 & 𠀁 & 20001 & 𠀂 & 20002 & 𠀃 & 20003 \\ 𠀄 & 20004 & 𠀅 & 20005 & 𠀆 & 20006 & 𠀇 & 20007 \\ 𠀈 & 20008 & 𠀉 & 20009 & 𠀊 & 2000A & 𠀋 & 2000B \\ @@ -2178,18 +3923,13 @@ Alignment with English characters. \end{table} \end{document} % \end{macrocode} -% \iffalse -%</example-fallback> -% \fi -% \Finale % -% \typeout{*************************************************************} -% \typeout{*} -% \typeout{* To finish the installation you have to move the following} -% \typeout{* files into a directory searched by XeTeX:} -% \typeout{*} -% \typeout{* \space\space\space xeCJK.sty} -% \typeout{*} -% \typeout{*************************************************************} +% \begin{macrocode} +%</ex-block> +% \end{macrocode} +% +% \end{implementation} +% % \Finale +% \endinput diff --git a/Master/texmf-dist/source/xelatex/xecjk/xeCJK.ins b/Master/texmf-dist/source/xelatex/xecjk/xeCJK.ins index 0c822f6c7ad..d791e0e4ca5 100644 --- a/Master/texmf-dist/source/xelatex/xecjk/xeCJK.ins +++ b/Master/texmf-dist/source/xelatex/xecjk/xeCJK.ins @@ -6,42 +6,57 @@ %% %% xeCJK.dtx (with options: `batchfile') %% -%% Version 2.4.5 (31-Jan-2012) +%% Version 3.0.4 (06-May-2012) +%% ----------------------------------------------------------------- +%% Author: Wenchang Sun <sunwch@hotmail.com> +%% Maintainer: Leo Liu <leoliu.pku@gmail.com> +%% Qing Lee <sobenlee@gmail.com> +%% Copyright (C) 2007--2012 Wenchang Sun %% -%% Copyright (C) Wenchang Sun <sunwch@hotmail.com> +%% This file may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% 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.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. %% -%% This file may be distributed and/or modified under the -%% conditions of the LaTeX Project Public License, either version 1.3 -%% 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.3 or later is part of all distributions of LaTeX -%% version 2005/12/01 or later. +%% This work has the LPPL maintenance status "maintained". +%% The Current Maintainer of this work are Leo Liu and Qing Lee. +%% ----------------------------------------------------------------- %% \input docstrip.tex \keepsilent \preamble - Version 2.4.5 (31-Jan-2012) + Version 3.0.4 (06-May-2012) +----------------------------------------------------------------- + Author: Wenchang Sun <sunwch@hotmail.com> + Maintainer: Leo Liu <leoliu.pku@gmail.com> + Qing Lee <sobenlee@gmail.com> + Copyright (C) 2007--2012 Wenchang Sun - Copyright (C) Wenchang Sun <sunwch@hotmail.com> + This file may be distributed and/or modified under the + conditions of the LaTeX Project Public License, either version 1.3 + 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.3 or later is part of all distributions of LaTeX + version 2005/12/01 or later. - This file may be distributed and/or modified under the - conditions of the LaTeX Project Public License, either version 1.3 - 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.3 or later is part of all distributions of LaTeX - version 2005/12/01 or later. + This work has the LPPL maintenance status "maintained". + The Current Maintainer of this work are Leo Liu and Qing Lee. +----------------------------------------------------------------- \endpreamble +\postamble +\endpostamble \askforoverwritefalse -\generate{\file{xeCJK.sty}{\from{xeCJK.dtx}{xeCJK}}} -\generate{\file{example-addspaces.tex}{\from{xeCJK.dtx}{example-addspaces}}} -\generate{\file{example-CJKchecksingle.tex}{\from{xeCJK.dtx}{example-CJKchecksingle}}} -\generate{\file{example-CJKfntef.tex}{\from{xeCJK.dtx}{example-CJKfntef}}} -\generate{\file{example-fallback.tex}{\from{xeCJK.dtx}{example-fallback}}} +\generate{\file{\jobname.sty}{\from{\jobname.dtx}{package}}} +\generate{\file{example-autofake.tex}{\from{\jobname.dtx}{ex-autofake}}} +\generate{\file{example-fallback.tex}{\from{\jobname.dtx}{ex-fallback}}} +\generate{\file{example-subCJKblock.tex}{\from{\jobname.dtx}{ex-block}}} \endbatchfile -\endinput +%% %% %% End of file `xeCJK.ins'. |