% \iffalse meta-comment % !TEX program = XeLaTeX %<*internal> \iffalse % %<*readme> hanzibox LaTeX3 Chinese Character package, v1.1.0 ======= `hanzibox` is a LaTeX package written to simplify the input of Chinese with Hanyu Pinyin and translation. Hanyu Pinyin was placed above Chinese with xpinyin package and the translation was placed below the Chinese. `hanzibox` is a utility for creating practise sheets, dialogs, character explanations and more. There are PDFs included which may be useful to regular users. It was inspired by hanzibox.sty from https://github.com/janvorisek/chinese-latex-utilities. In this new package, the commands were kept, but redesign its options and mandatories. At present, hanzibox.sty only supports XeTeX engines and only allows UTF-8 encoding tex source file. You can read the package manual (in Chinese) for more detailed explanations. Contributing ------------ Gitee repository: https://gitee.com/nwafu_nan/hanzibox-l3. Issues and pull requests are welcome. Copyright and Licence --------------------- Copyright (C) 2020-2021 by Nan Geng ---------------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. This version of this license is in http://www.latex-project.org/lppl/lppl-1-3c.txt and 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 is Nan Geng. This package consists of the file hanzibox.dtx, and the derived files hanzibox.sty, hanzibox.pdf, hanzibox.ins, README.md (this file). % %<*internal> \fi \begingroup \def\temp{LaTeX2e} \expandafter\endgroup\ifx\temp\fmtname\else \csname fi\endcsname % %<*install> \input ctxdocstrip % \let\MetaPrefix\relax \preamble Copyright (C) 2020-2021 by Nan Geng -------------------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. This version of this license is in http://www.latex-project.org/lppl/lppl-1-3c.txt and 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 is Nan Geng. -------------------------------------------------------------------------- \endpreamble \postamble This package consists of the file hanzibox.dtx, and the derived files hanzibox.sty, hanzibox.pdf, hanzibox.ins, README.md. \endpostamble \declarepostamble\emptypostamble \endpostamble \def\MetaPrefix{-- } \let\MetaPrefix\DoubleperCent \generate { % %<*internal> \usedir{source/xelatex/hanzibox} \file{hanzibox.ins} {\from{\jobname.dtx}{install}} % %<*install> \usedir{xetex/xelatex/hanzibox} \file{hanzibox.sty} {\from{\jobname.dtx}{package}} \nopreamble\nopostamble \usedir{doc/xelatex/hanzibox} \file{README.md} {\from{\jobname.dtx}{readme}} } \endbatchfile % %<*internal> \fi % %\NeedsTeXFormat{LaTeX2e}[2020/10/01] %\RequirePackage{expl3} %<+package>\GetIdInfo$Id: hanzibox.dtx 1.1.0 2021-09-23 08:00:00 +0800 Nan Geng $ % {Boxed Chinese characters with Pinyin above and translation below.} %\ProvidesExplPackage{\ExplFileName} % {\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} %<*driver> \documentclass{ctxdoc} \usepackage{listings} \usepackage{xcolor} \usepackage{xcolor-material} \usepackage{hanzibox} \renewcommand*\marg[1]{\{\meta{#1}\}} \renewcommand*\oarg[1]{[\meta{#1}]} \renewcommand*\parg[1]{(\meta{#1})} \DeclareDocumentCommand\opt{m}{\texttt{#1}} \DeclareDocumentCommand\kvopt{mm} {\texttt{#1\breakablethinspace=\breakablethinspace#2}} \def\breakablethinspace{\hskip 0.16667em\relax} \begin{document} \DocInput{\jobname.dtx} \IndexLayout \PrintChanges \PrintIndex \end{document} % % \fi % % \changes{v1.0.0}{2021/09/18}{开始编写模板。} % % \CheckSum{420} % \GetFileId{hanzibox.sty} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \title{\bfseries\pkg{hanzibox}:田字格-米字格汉字练习宏包} % \author{耿楠\\ \path{nangeng@nwafu.edu.cn}} % \date{\filedate\qquad\fileversion\thanks{\url{https://gitee.com/nwafu_nan/hanzibox-l3}.}} % \maketitle % % \begin{documentation} % % \begin{abstract} % % \pkg{hanzibox} 是一个用\LaTeX3开发的 \LaTeX 宏包,它提供了\tn{hanzidialog}和\tn{hanzibox} % 两个命令。这两个命令用于输出汉字学习中的田字格或米字格,并可以根据需要在汉字正上方显示拼音, % 在正下方显示需要的译文。其中,\tn{hanzidialog}命令的注音功能通过手动插入\pkg{xpinyin}宏包的 % \tn{pinyin}命令实现。\tn{hanzibox}命令的注音功能自动调用\pkg{xpinyin}宏包的\tn{pinyin}命令实现, % 并且\tn{hanzibox}命令提供了\tn{hanzibox*}星号版本,该星号版本能够根据汉字自动调用 % \pkg{xpinyin}宏包的\tn{xpinyin*}命令实现汉字注音。 % % \end{abstract} % % \section{简要说明} % % \pkg{hanzibox} 是一个用于输出汉字学习中的田字格或米字格,并在汉字正上方显示拼音, % 在正下方显示需要的译文。同时,也可以根据需要隐藏拼音、汉字或译文。 % % 使用\pkg{hanzibox}宏包的\LaTeX 源文件需采用 \texttt{UTF-8}编码,并且需使用\XeLaTeX 进行编译。 % % \pkg{hanzibox} 依赖 \package{l3kernel} 和 \package{l3packages}。 % % \section{用户接口} % % \begin{function}[added=2021-09-18,updated=2021-09-19]{\hanzidialog} % \begin{syntax} % \tn{hanzidialog} \Arg{汉字} \oarg{拼音选项} \oarg{译文选项} % \end{syntax} % 排版汉字,并根据选项内容在顶部排版拼音,在底部排版译文。\\ % 其中,\oarg{拼音选项}可以是任意文本,如果是汉语拼音则需要使用\pkg{xpinyin}宏包的 % \tn{pinyin}命令进行处理;\oarg{译文选项}可以是任意文本。 % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.3\linewidth,gobble=5] % \hanzidialog{王老师}[Wang \pinyin{lao3shi1}][teacher wang] % \hanzidialog{王老师}[Wang \pinyin{lao3shi1}][王先生] % \end{SideBySideExample} % \end{function} % % \begin{function}[added=2021-09-18,updated=2021-09-20]{\hanzibox,\hanzibox*} % \begin{syntax} % \tn{hanzibox} \oarg{外观选项} \Arg{汉字} \oarg{拼音选项} \oarg{译文选项} % \tn{hanzibox*} \oarg{外观选项} \Arg{汉字} \oarg{拼音选项} \oarg{译文选项} % \end{syntax} % 排版汉字,并根据选项内容在顶部排版拼音,在底部排版译文。\\ % 其中,\oarg{外观选项}用于设置盒子外观;\oarg{拼音选项}用于设置拼音, % 要求其拼音格式符合\pkg{xpinyin}宏包的规定;\oarg{译文选项}可以是任意文本。 % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.43\linewidth,gobble=5] % \hanzibox[inner=none,border=false]{我}[wo3][me] % \hanzibox[inner=cross,border=true]{我}[wo3][吾] % \hanzibox[inner=star]{我}[wo3][俺] % \hanzibox[borderwidth=1.5pt]{我}[wo3][爷] % \hanzibox[bordercolor=red]{我}[wo3][山人] % \end{SideBySideExample} % 星号命令用于根据汉字自动在顶部排版拼音,在底部排版译文。\\ % 此时,\oarg{拼音选项}中的拼音无效,可以留空,但若有译文则该选项不可省略; % \oarg{译文选项}可以是任意文本。\\ % 注意:此时的注音由\pkg{xpinyin}宏包实现,如需要设置多音字的拼音,请参阅其宏包说明。 % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.43\linewidth,gobble=5] % \hanzibox*[inner=none,border=false]{我}[][me] % \hanzibox*[inner=cross,border=true]{我}[][吾] % \hanzibox*[inner=star]{我}[wo3][不才] % \hanzibox*[borderwidth=1.5pt]{我}[wo2][本人] % \hanzibox*[bordercolor=red]{我}[ni3][孤家] % \end{SideBySideExample} % \end{function} % % \section{选项说明} % % \begin{function}[added=2021-09-20]{\hanziboxset} % \begin{syntax} % \tn{hanziboxset} \marg{键值列表} % \end{syntax} % 本宏包提供了一系列选项,以实现汉字盒子外观样式设置。 % 载入\pkg{hanzibox}宏包后,以下选项均可通过统一的\tn{hanziboxset}命令进行设置。 % 同时,这些选项也可以通过\tn{hanzibox}命令的外观选项进行设置。 % \end{function} % % \tn{hanziboxset} 的参数是一组由(英文)逗号隔开的选项列表, % 列表中的选项通常是 \kvopt{\meta{key}}{\meta{value}} 形式。 % 部分选项的\meta{value} 可以省略。对于同一项,后续设置会覆盖以前的设置。 % 在下文的说明中,将用\textbf{粗体}表示默认值。 % % \tn{hanziboxset} 采用 \LaTeX3 风格的键值设置,支持不同类型以及多种 % 层次的选项设定。键值列表中,“|=|”左右的空格不影响设置;但需注意, % 参数列表中\textbf{不可以出现空行}。 % % 布尔型的参数 \kvopt{\meta{选项}}{true} 中的“|= true|”可以省略。 % % \changes{v1.1.0}{2021/09/22}{添加外观选项设置命令示例代码。} % % \begin{frameverb} % \hanziboxset{ % scale = 0.8, % 整体缩放比例 % inner = star, % 盒子内部图案 % border = true, % 是否有边框 % borderwidth = 1.5 pt, % 边框宽度 % bordercolor = red, % 边框颜色 % fgcolor = red, % 盒子前景色(文字颜色) % bgcolor = yellow!50, % 盒子背景色 % withpinyin = false, % 是否显示拼音 % withhanzi = true, % 是否显示汉字 % withtran = true % 是否显示译文 % } % \end{frameverb} % % 注:各选项也可以以相同的键值列表在汉字盒子命令的外观选项中进行设置。 % % \subsection{缩放比例} % % \changes{v1.1.0}{2021/09/22}{将缩放比例键ratio改为scale。} % % \begin{function}[added=2021-09-20,updated=2021-09-22]{scale} % \begin{syntax} % scale = \Arg{number} % \end{syntax} % 设置\tn{hanzibox}命令绘制汉字盒子及其拼音和译文的整体缩放比例,默认值为\textbf{1.0}。 % \end{function} % % \subsection{汉字边框} % % \begin{function}[added=2021-09-20]{border} % \begin{syntax} % border = <\TTF> % \end{syntax} % 为\tn{hanzibox}命令选择是否绘制汉字的边框,默认值为\textbf{true}。该选项对\tn{hanzidialog}命令无效。 % \end{function} % % \begin{function}[added=2021-09-20]{borderwidth} % \begin{syntax} % borderwidth = \Arg{dimen} % \end{syntax} % 为\tn{hanzibox}命令设置汉字的边框宽度,默认值为\textbf{0.4pt}。该选项对\tn{hanzidialog}命令无效。 % \end{function} % % \begin{function}[added=2021-09-20]{bordercolor} % \begin{syntax} % bordercolor = \Arg{color} % \end{syntax} % 为\tn{hanzibox}命令设置汉字的边框颜色,默认值为\textbf{black}。该选项对\tn{hanzidialog}命令无效。 % \end{function} % % \changes{v1.1.0}{2021/09/21}{添加前景颜色设置选项。} % % \begin{function}[added=2021-09-21]{fgcolor} % \begin{syntax} % fgcolor = \Arg{color} % \end{syntax} % 为\tn{hanzibox}命令设置汉字盒子前景颜色(文字颜色), % 默认值为\textbf{black}。该选项对\tn{hanzidialog}命令无效。 % \end{function} % % \changes{v1.1.0}{2021/09/21}{添加背景颜色设置选项。} % % \begin{function}[added=2021-09-21]{bgcolor} % \begin{syntax} % bgcolor = \Arg{color} % \end{syntax} % 为\tn{hanzibox}命令设置汉字盒子背景颜色(填充颜色), % 默认值为\textbf{white}。该选项对\tn{hanzidialog}命令无效。 % \end{function} % % \subsection{格子样式} % % \begin{function}[added=2021-09-20]{inner} % \begin{syntax} % inner = <(none)|star|cross> % \end{syntax} % 为\tn{hanzibox}命令设置汉字盒子内部装饰为无(none)、米字格(star)或田字格(cross), % 默认值为\textbf{none}。该选项对\tn{hanzidialog}命令无效。 % \end{function} % % \changes{v1.1.0}{2021/09/21}{添加隐藏拼音选项。} % % \subsection{内容隐藏} % % \begin{function}[added=2021-09-21]{withpinyin} % \begin{syntax} % withpinyin = <\TTF> % \end{syntax} % 为\tn{hanzibox}命令选择是否输出拼音,默认值为\textbf{true}。该选项对\tn{hanzidialog}命令无效。 % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.35\linewidth,gobble=5] % \hanzibox[inner=cross]{我}[wo3][吾] % \hanzibox[withpinyin=false,inner=star]{我}[wo3][不才] % \hanzibox[bordercolor=red]{我们}[wo3men5][吾辈] % \end{SideBySideExample} % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.35\linewidth,gobble=5] % \hanzibox*[inner=cross]{我}[][吾] % \hanzibox*[withpinyin=false,inner=star]{我}[wo3][不才] % \hanzibox*[bordercolor=red]{我们}[wo3][吾辈] % \end{SideBySideExample} % \end{function} % % \changes{v1.1.0}{2021/09/21}{添加隐藏汉字选项。} % % \begin{function}[added=2021-09-21]{withhanzi} % \begin{syntax} % withhanzi = <\TTF> % \end{syntax} % 为\tn{hanzibox}命令选择是否输出汉字,默认值为\textbf{true}。该选项对\tn{hanzidialog}命令无效。 % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.35\linewidth,gobble=5] % \hanzibox[inner=cross]{我}[wo3][吾] % \hanzibox[withhanzi=false,inner=star]{我}[wo3][不才] % \hanzibox[bordercolor=red]{我们}[wo3men5][吾辈] % \end{SideBySideExample} % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.35\linewidth,gobble=5] % \hanzibox*[inner=cross]{我}[][吾] % \hanzibox*[withhanzi=false,inner=star]{我}[wo3][不才] % \hanzibox*[bordercolor=red]{我们}[wo3][吾辈] % \end{SideBySideExample} % \end{function} % % \changes{v1.1.0}{2021/09/21}{添加隐藏译文选项。} % % \begin{function}[added=2021-09-21]{withtran} % \begin{syntax} % withtran = <\TTF> % \end{syntax} % 为\tn{hanzibox}命令选择是否输出译文,默认值为\textbf{true}。该选项对\tn{hanzidialog}命令无效。 % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.35\linewidth,gobble=5] % \hanzibox[inner=cross]{我}[wo3][吾] % \hanzibox[withtran=false,inner=star]{我}[wo3][不才] % \hanzibox[bordercolor=red]{我们}[wo3men5][吾辈] % \end{SideBySideExample} % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.35\linewidth,gobble=5] % \hanzibox*[inner=cross]{我}[][吾] % \hanzibox*[withtran=false,inner=star]{我}[wo3][不才] % \hanzibox*[bordercolor=red]{我们}[wo3][吾辈] % \end{SideBySideExample} % \end{function} % % \end{documentation} % % \StopEventually{} % % \begin{implementation} % % \section{代码实现} % % 本宏包使用 \LaTeX3 语法编写,依赖 \pkg{expl3} 环境, % 并需调用 \pkg{l3packages} 中的相关宏包。 % % 按照 \LaTeX3 语法,代码中的空格、换行、回车与制表符完全被忽略, % 而下划线“|_|”和冒号“|:|”则可作为一般字母使用。 % 正常的空格可以使用“|~|”代替;至于 |~| 原来所表示的“带子”, % 则要用 \LaTeXe{} 的原始命令 \tn{nobreakspace} 代替。 % % 以下代码中有一些形如 \textcolor[HTML]{2E3191}{\textsf{<*package>}} % 的标记,这是 \pkg{DocStrip} 中的“guard”,用来选择性地提取文件。 % “\textsf{*}”和“\textsf{/}”分别表示该部分的开始和结束。不含 % “\textsf{*}”和“\textsf{/}”的 guard 出现在行号右侧,它们用来确定 % 单独一行代码的归属。这些 guard 的颜色深浅不一,用以明确嵌套关系。 % % 另有若干形如 \textcolor[HTML]{AD1457}{\textsf{<@@=hanzibox>}} 的 guard, % 它们由 \pkg{l3docstrip} 定义,用来标识名字空间(模块)。 % % \subsection{环境检测与准备} % % \begin{macrocode} %<*package> %<@@=hanzibox> % \end{macrocode} % % 载入必要的宏包 % % \begin{macrocode} \RequirePackage { xtemplate, l3keys2e, xparse } % \end{macrocode} % % 检查LaTeX3宏包版本 % % \begin{macrocode} % \clist_map_inline:nn { xtemplate, l3keys2e } % { % \@ifpackagelater {#1} { 2020/07/17 } % { } { \msg_error:nnn { hanzibox } { l3-too-old } {#1} } % } % \msg_new:nnn { hanzibox } { l3-too-old } % { % Package~ "#1"~ is~ too~ old. \\\\ % Please~ update~ an~ up-to-date~ version~ of~ the~ bundles \\ % "l3kernel"~ and~ "l3packages"~ using~ your~ TeX~ package \\ % manager~ or~ from~ CTAN. % } % % \end{macrocode} % % 检查编译引擎 % % \begin{macrocode} \sys_if_engine_xetex:F { \msg_fatal:nnx { hanzibox } { unsupported-engine } { \c_sys_engine_str } } \msg_new:nnn { hanzibox } { unsupported-engine } { The~ hanzibox~ packages~ requires~ either~ XeTeX. \\\\ "#1"~ is~ not~ supported~ at~ present.~ You~ must~ change \\ your~ typesetting~ engine~ to~ "xelatex"~ or~ "lualatex". } % \end{macrocode} % % 载入TikZ, xpinyin宏包 % % \begin{macrocode} \RequirePackage { tikz, xpinyin } % \end{macrocode} % % 在Expl3中使用TikZ库的补丁 % % \begin{macrocode} \RequirePackage{etoolbox} \ExplSyntaxOff \patchcmd {\pgfutil@InputIfFileExists} {\input #1} {% \@pushfilename \xdef\@currname{#1}% \input #1 % \@popfilename } {}{} \ExplSyntaxOn \usetikzlibrary{decorations} \usetikzlibrary{shapes.geometric} \usetikzlibrary{positioning} % \end{macrocode} % % TikZ样式设置 % % \begin{macrocode} \tikzset{% stretch~dash/.code~args={on~#1~off~#2}{% \tikz@addoption{% \pgfgetpath\currentpath% \pgfprocessround{\currentpath}{\currentpath}% \pgf@decorate@parsesoftpath{\currentpath}{\currentpath}% \pgfmathparse{max(round((\pgf@decorate@totalpathlength-#1)/(#1+#2)),0)}% \let\npattern=\pgfmathresult% \pgfmathparse{\pgf@decorate@totalpathlength/(\npattern*(#1+#2)+#1)}% \let\spattern=\pgfmathresult% \pgfsetdash{{\spattern*#1}{\spattern*#2}}{0pt}% }% }% } % \end{macrocode} % % \subsection{用户接口} % % \changes{v1.1.0}{2021/09/22}{为用户命令添加组限制。} % % \begin{macro}{\hanzidialog} % 手动汉字盒子命令。 % \begin{macrocode} \NewDocumentCommand{\hanzidialog}{ m O{} O{} } { \group_begin: \@@_dialog:nnnn { #1 } { #2 } { #3 } \group_end: } % \end{macrocode} % \end{macro} % % \begin{macro}{\hanzibox} % 自动拼音汉字盒子命令。 % \begin{macrocode} \NewDocumentCommand{\hanzibox}{ s O{} m O{} O{} } { \IfBooleanTF{#1} { \group_begin: \@@_asterisk_draw:nnnn { #2 } { #3 } { #4 } { #5 } \group_end: }{ \group_begin: \@@_draw:nnnn { #2 } { #3 } { #4 } { #5 } \group_end: } } % \end{macrocode} % \end{macro} % % \subsection{内部变量声明} % % \changes{v1.1.0}{2021/09/21}{添加缩放比例,前景/背景色,隐藏控制变量。} % % \begin{variable}{\fp_new:N \l_@@_scale_fp, % \l_@@_inner_int, % \l_@@_border_bool, % \l_@@_borderwidth_dim, % \l_@@_bordercolor_tl, % \l_@@_fgcolor_tl, % \l_@@_bgcolor_tl, % \l_@@_pinyin_bool, % \l_@@_hanzi_bool, % \l_@@_tran_bool, % \l_@@_pinyin_tl, % \l_@@_character_tl, % \l_@@_translation_tl, % \l_@@_pinyin_int, % \l_@@_character_int, % \l_@@_translation_int % } % 临时变量。 % % \begin{macrocode} \fp_new:N \l_@@_scale_fp \int_new:N \l_@@_inner_int \bool_new:N \l_@@_border_bool \dim_new:N \l_@@_borderwidth_dim \tl_new:N \l_@@_bordercolor_tl \tl_new:N \l_@@_fgcolor_tl \tl_new:N \l_@@_bgcolor_tl \bool_new:N \l_@@_pinyin_bool \bool_new:N \l_@@_hanzi_bool \bool_new:N \l_@@_tran_bool \tl_new:N \l_@@_pinyin_tl \tl_new:N \l_@@_character_tl \tl_new:N \l_@@_translation_tl \int_new:N \l_@@_pinyin_int \int_new:N \l_@@_character_int \int_new:N \l_@@_translation_int % \end{macrocode} % \end{variable} % % % \subsection{选项处理} % % 定义 |hanzibox| 键值类。 % \begin{macrocode} \keys_define:nn { hanzibox } { % \end{macrocode} % % \changes{v1.1.0}{2021/09/21}{添加缩放比例键。} % % \begin{macro}{scale} % 设置汉字及其拼音和译文的整体缩放比例。 % \begin{macrocode} scale .fp_set:N = \l_@@_scale_fp, scale .initial:n = 1.0, % \end{macrocode} % \end{macro} % % \begin{macro}{inner} % 设置汉字格子内部样式,有空白、米字和十字3种样式,默认为空白样式。 % \begin{macrocode} inner .choice:, inner .value_required:n = true, inner .choices:nn = { none,star,cross } { \int_set_eq:NN \l_@@_inner_int \l_keys_choice_int }, inner .initial:n = none, % \end{macrocode} % \end{macro} % % \begin{macro}{border} % 是否绘制汉字盒子边框,默认为空true。 % \begin{macrocode} border .bool_set:N = \l_@@_border_bool, border .default:n = true, border .initial:n = true, % \end{macrocode} % \end{macro} % % \begin{macro}{borderwidth} % 汉字盒子边框宽度,默认为空3 pt。 % \begin{macrocode} borderwidth .dim_set:N = \l_@@_borderwidth_dim, borderwidth .initial:n = 0.4 pt, % \end{macrocode} % \end{macro} % % \begin{macro}{bordercolor} % 汉字盒子边框颜色,默认为black。 % \begin{macrocode} bordercolor .tl_set:N = \l_@@_bordercolor_tl, bordercolor .initial:n = black, % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/21}{添加前景颜色键。} % % \begin{macro}{fgcolor} % 汉字盒子前景颜色(文字颜色),默认为black。 % \begin{macrocode} fgcolor .tl_set:N = \l_@@_fgcolor_tl, fgcolor .initial:n = black, % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/21}{添加背景颜色键。} % % \begin{macro}{bgcolor} % 汉字盒子背景颜色,默认为black。 % \begin{macrocode} bgcolor .tl_set:N = \l_@@_bgcolor_tl, bgcolor .initial:n = white, % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/21}{添加隐藏拼音键。} % % \begin{macro}{withpinyin} % 是否显示汉语拼音,默认为true。 % \begin{macrocode} withpinyin .bool_set:N = \l_@@_pinyin_bool, withpinyin .default:n = true, withpinyin .initial:n = true, % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/21}{添加隐藏汉字键。} % % \begin{macro}{withhanzi} % 是否显示汉语拼音,默认为true。 % \begin{macrocode} withhanzi .bool_set:N = \l_@@_hanzi_bool, withhanzi .default:n = true, withhanzi .initial:n = true, % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/21}{添加隐藏译文键。} % % \begin{macro}{withtran} % 是否显示汉语拼音,默认为true。 % \begin{macrocode} withtran .bool_set:N = \l_@@_tran_bool, withtran .default:n = true, withtran .initial:n = true, % \end{macrocode} % \end{macro} % % % 处理未知选项。 % \begin{macrocode} unknown .code:n = { \@@_error:n { unknown-option } } } \msg_new:nnn { hanzibox } { unknown-option } { package~ option~ "\l_keys_key_tl"~ is~ unknown. } % \end{macrocode} % % \subsection{选项用户接口} % % \begin{macro}{\hanziboxset} % 选项设置用户接口。 % \begin{macrocode} \NewDocumentCommand \hanziboxset { m } { \keys_set:nn { hanzibox } {#1} } % \end{macrocode} % \end{macro} % % \subsection{内部函数} % % \begin{macro}{\@@_dialog:nnnn} % 手动汉字盒子排版内部命令,根据选项用TikZ实现绘制。 % \begin{macrocode} \cs_new_protected:Npn \@@_dialog:nnnn #1#2#3 { \tl_set:Nx \l_@@_character_tl {#1} \tl_set:Nx \l_@@_pinyin_tl {#2} \tl_set:Nx \l_@@_translation_tl {#3} \scalebox{\fp_use:N \l_@@_scale_fp}{ \tikz[scale=0.5, every~node/.style={inner~sep=0,outer~sep=0}]{% {\node[] at (1,1){\huge{\l_@@_character_tl}}}; {\node[label={\strut\small\textbf{\l_@@_pinyin_tl}}, text~height=1cm] (charr) at (1,1){};}% {\node[align=center] at (1,-0.5) {\strut\small\textit{\l_@@_translation_tl}};}% }% }% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@_pinyinaux:n} % \begin{macro}{\@@_pinyinaux:x} % \pkg{xpyinyin}宏包\tn{pinyin} 命令的\LaTeX3{}版本函数及其函数变体。 % \begin{macrocode} \cs_set_eq:NN \@@_pinyinaux:n \pinyin \cs_generate_variant:Nn \@@_pinyinaux:n { x } % \end{macrocode} % \end{macro} % \end{macro} % % \changes{v1.1.0}{2021/09/21}{添加整体缩放代码。} % \changes{v1.1.0}{2021/09/21}{添加按需要隐藏拼音、汉字或译文代码。} % \changes{v1.1.0}{2021/09/21}{将隐藏功能修正为用前景/背景色实现。} % \changes{v1.1.0}{2021/09/22}{将各部分绘制分解为函数实现。} % % \begin{macro}{\@@_draw:nnnn} % 自动汉字盒子排版内部命令,根据选项用TikZ实现绘制。 % \begin{macrocode} \cs_new_protected:Npn \@@_draw:nnnn #1#2#3#4 { % \end{macrocode} % % 设置盒子外观选项 % % \begin{macrocode} \keys_set:nn { hanzibox } { #1 } % \end{macrocode} % % 将各参数存入token list变量,注意使用x递归展开 % % \begin{macrocode} \tl_set:Nx \l_@@_character_tl {#2} \tl_set:Nx \l_@@_pinyin_tl {#3} \tl_set:Nx \l_@@_translation_tl {#4} % \end{macrocode} % % 计算token list中的内容长度(个数) % % \begin{macrocode} \int_set:Nn \l_@@_character_int { \tl_count:V \l_@@_character_tl } \int_set:Nn \l_@@_pinyin_int { \tl_count:V \l_@@_pinyin_tl } \int_set:Nn \l_@@_translation_int { \tl_count:V \l_@@_translation_tl } \scalebox{\fp_use:N \l_@@_scale_fp}{ \tikz[scale=0.5, every~node/.style={inner~sep=0,outer~sep=0}]{% % \end{macrocode} % % 根据汉字长度绘制汉字盒子背景,必须提前绘制 % % \begin{macrocode} \@@_border_draw:n {0.0cm} % \end{macrocode} % % 如果显示汉字,则内部格线应该提前绘制 % % \begin{macrocode} \bool_if:NT \l_@@_hanzi_bool { \@@_frame_background:n {0.0cm} } \int_compare:nNnTF { \l_@@_character_int } = {0} { \bool_if:NTF \l_@@_hanzi_bool { \node[\l_@@_fgcolor_tl] at (1,1){\huge{\l_@@_character_tl}}; }{ \node[\l_@@_bgcolor_tl] at (1,1){\huge{\l_@@_character_tl}}; } \bool_if:NTF \l_@@_pinyin_bool { \node[label={[font=\small,text=\l_@@_fgcolor_tl] \strut\@@_pinyinaux:x {\l_@@_pinyin_tl}}, text~height=1cm] (charr) at (1,1){}; }{ \node[label={[font=\small,text=\l_@@_bgcolor_tl] \strut\@@_pinyinaux:x {\l_@@_pinyin_tl}}, text~height=1cm] (charr) at (1,1){}; } \@@_tran_draw:nn {1}{-0.5} } { \bool_if:NTF \l_@@_hanzi_bool { \node[\l_@@_fgcolor_tl] at (1*\l_@@_character_int,1) {\huge\tl_use:N \l_@@_character_tl}; }{ \node[\l_@@_bgcolor_tl] at (1*\l_@@_character_int,1) {\huge\tl_use:N \l_@@_character_tl}; } \bool_if:NTF \l_@@_pinyin_bool { \node[label={[font=\small,text=\l_@@_fgcolor_tl] \strut\@@_pinyinaux:x {\l_@@_pinyin_tl}}, text~height=1cm] (charr) at (1*\l_@@_character_int,1){}; }{ \node[label={[font=\small,text=\l_@@_bgcolor_tl] \strut\@@_pinyinaux:x {\l_@@_pinyin_tl}}, text~height=1cm] (charr) at (1*\l_@@_character_int,1){}; } \@@_tran_draw:nn {\l_@@_character_int}{-0.5} } % \end{macrocode} % % 如果不显示汉字,则内部格线应该最后绘制 % % \begin{macrocode} \bool_if:NF \l_@@_hanzi_bool { \@@_frame_background:n {0.0cm} } }% }% } % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/21}{添加\tn{hanzibox*}星号命令的内部实现代码。} % \changes{v1.1.0}{2021/09/21}{添加按需要隐藏拼音、汉字或译文代码。} % \changes{v1.1.0}{2021/09/21}{将隐藏功能修正为用前景/背景色实现。} % \changes{v1.1.0}{2021/09/22}{将各部分绘制分解为函数实现。} % % \begin{macro}{\@@_asterisk_draw:nnnn} % 自动汉字拼音盒子排版内部命令,根据选项用TikZ实现绘制。 % \begin{macrocode} \cs_new_protected:Npn \@@_asterisk_draw:nnnn #1#2#3#4 { % \end{macrocode} % % 设置盒子外观选项 % % \begin{macrocode} \keys_set:nn { hanzibox } { #1 } % \end{macrocode} % % 将各参数存入token list变量,注意使用x递归展开 % % \begin{macrocode} \tl_set:Nx \l_@@_character_tl {#2} \tl_set:Nx \l_@@_pinyin_tl {#3} \tl_set:Nx \l_@@_translation_tl {#4} % \end{macrocode} % % 计算token list中的内容长度(个数) % % \begin{macrocode} \int_set:Nn \l_@@_character_int { \tl_count:V \l_@@_character_tl } \int_set:Nn \l_@@_pinyin_int { \tl_count:V \l_@@_pinyin_tl } \int_set:Nn \l_@@_translation_int { \tl_count:V \l_@@_translation_tl } \scalebox{\fp_use:N \l_@@_scale_fp}{ \tikz[scale=0.5, every~node/.style={inner~sep=0,outer~sep=0}]{% % \end{macrocode} % % 根据汉字长度绘制汉字盒子背景,必须提前绘制 % % \begin{macrocode} \@@_border_draw:n {-0.5cm} % \end{macrocode} % % 如果显示汉字,则内部格线应该提前绘制 % % \begin{macrocode} \bool_if:NT \l_@@_hanzi_bool { \@@_frame_background:n {-0.5cm} } \int_compare:nNnTF { \l_@@_character_int } = {0} { \bool_if:NTF \l_@@_pinyin_bool { \bool_if:NTF \l_@@_hanzi_bool { \node[\l_@@_fgcolor_tl] at (1,1) {\huge{\xpinyin*[format={\small\color{\l_@@_fgcolor_tl}}, vsep=0.90 cm]{\l_@@_character_tl}}}; }{ \node[\l_@@_bgcolor_tl] at (1,1) {\huge{\xpinyin*[format={\small\color{\l_@@_fgcolor_tl}}, vsep=0.90 cm]{\l_@@_character_tl}}}; } }{ \bool_if:NTF \l_@@_hanzi_bool { \node[\l_@@_fgcolor_tl] at (1,1) {\huge{\xpinyin*[format={\small\color{\l_@@_bgcolor_tl}}, vsep=0.90 cm]{\l_@@_character_tl}}}; }{ \node[\l_@@_fgcolor_tl] at (1,1) {\huge{\xpinyin*[format={\small\color{\l_@@_bgcolor_tl}}, vsep=0.90 cm]{\l_@@_character_tl}}}; } } \@@_tran_draw:nn {1}{-1.0} } { \bool_if:NTF \l_@@_pinyin_bool { \bool_if:NTF \l_@@_hanzi_bool { \node[\l_@@_fgcolor_tl] at (1*\l_@@_character_int,1) {\huge{\xpinyin*[format={\small\color{\l_@@_fgcolor_tl}}, vsep=0.90 cm]{\l_@@_character_tl}}}; }{ \node[\l_@@_bgcolor_tl] at (1*\l_@@_character_int,1) {\huge{\xpinyin*[format={\small\color{\l_@@_fgcolor_tl}}, vsep=0.90 cm]{\l_@@_character_tl}}}; } }{ \bool_if:NTF \l_@@_hanzi_bool { \node[\l_@@_fgcolor_tl] at (1*\l_@@_character_int,1) {\huge{\xpinyin*[format={\small\color{\l_@@_bgcolor_tl}}, vsep=0.90 cm]{\l_@@_character_tl}}}; }{ \node[\l_@@_fgcolor_tl] at (1*\l_@@_character_int,1) {\huge{\xpinyin*[format={\small\color{\l_@@_bgcolor_tl}}, vsep=0.90 cm]{\l_@@_character_tl}}}; } } \@@_tran_draw:nn {\l_@@_character_int}{-1.0} } % \end{macrocode} % % 如果不显示汉字,则内部格线应该最后绘制 % % \begin{macrocode} \bool_if:NF \l_@@_hanzi_bool { \@@_frame_background:n {-0.5cm} } }% }% } % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/22}{添加方格背景绘制内部函数。} % % \begin{macro}{\@@_frame_background:n} % TikZ米字格绘制代码。 % \begin{macrocode} \cs_new_protected:Npn \@@_frame_background:n #1 { \int_compare:nNnT { \l_@@_character_int } < {2} { \int_case:nn {\l_@@_inner_int} { {1}{ } {2}{ \@@_star_background:n {#1} } {3}{ \@@_cross_background:n {#1} } } } } % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/22}{添加米字格内部函数。} % % \begin{macro}{\@@_star_background:n} % TikZ米字格绘制代码。 % \begin{macrocode} \cs_new_protected:Npn \@@_star_background:n #1 { \draw[stretch~dash=on~2pt~off~2pt,thin, yshift=#1, \l_@@_bordercolor_tl!50](0,0)--(2,2);% \draw[stretch~dash=on~2pt~off~2pt,thin, yshift=#1, \l_@@_bordercolor_tl!50](0,2)--(2,0);% \draw[stretch~dash=on~2pt~off~2pt,thin, yshift=#1, \l_@@_bordercolor_tl!50](0,1)--(2,1);% \draw[stretch~dash=on~2pt~off~2pt,thin, yshift=#1, \l_@@_bordercolor_tl!50](1,0)--(1,2);% } % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/22}{添加田字格背景内部函数。} % % \begin{macro}{\@@_cross_background:n} % TikZ田字格绘制代码。 % \begin{macrocode} \cs_new_protected:Npn \@@_cross_background:n #1 { \draw[stretch~dash=on~2pt~off~2pt,thin, yshift=#1, \l_@@_bordercolor_tl!50](0,1)--(2,1);% \draw[stretch~dash=on~2pt~off~2pt,thin, yshift=#1, \l_@@_bordercolor_tl!50](1,0)--(1,2);% } % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/22}{添加背景方格内部函数。} % % \begin{macro}{\@@_border_draw:n} % 绘制边框代码。 % \begin{macrocode} \cs_new_protected:Npn \@@_border_draw:n #1 { \int_compare:nNnTF { \l_@@_character_int } = {0} { \draw[fill=\l_@@_bgcolor_tl,line~width=\l_@@_borderwidth_dim, yshift=#1, draw=\l_@@_bordercolor_tl] (0,0) rectangle(2,2); } { \bool_if:NTF \l_@@_border_bool { \draw[fill=\l_@@_bgcolor_tl,line~width=\l_@@_borderwidth_dim, yshift=#1, draw=\l_@@_bordercolor_tl] (0,0) rectangle(2*\l_@@_character_int,2); }{} } } % \end{macrocode} % \end{macro} % % \changes{v1.1.0}{2021/09/22}{添加译文文本绘制内部函数。} % % \begin{macro}{\@@_tran_draw:nn} % 绘制译文文本。 % \begin{macrocode} \cs_new_protected:Npn \@@_tran_draw:nn #1#2 { \bool_if:NTF \l_@@_tran_bool { \node[align=center,\l_@@_fgcolor_tl] at (1*#1,#2) {\strut\small\textit{\l_@@_translation_tl}}; }{ \node[align=center,\l_@@_bgcolor_tl] at (1*#1,#2) {\strut\small\textit{\l_@@_translation_tl}}; } } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \Finale % \endinput