% \iffalse meta-comment
% !TEX program = XeLaTeX
%
% DO NOT REMOVE THE MARK MANUALLY (used in l3build) -> %
%
%<package|doc-sty>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesExplPackage{hustvisual}
%<doc-sty>\ProvidesExplPackage{hustvisual-doc}
%<package|doc-sty>  {2025-05-07}{1.0.0} %
%<package>  {Visual Identity of Huazhong University of Science and Technology}
%<doc-sty>  {Docmentation Style for hustvisual}
%<*driver>
\documentclass{ctexart}
\usepackage{useclass}
\useclass*[full]{l3doc}
\usepackage{hustvisual}
\usepackage{hustvisual-doc}
\usepackage{mdframed}
\usepackage{marginnote}
\usepackage{siunitx}

\providecommand{\name}{\jobname}
\providecommand{\pkgname}{\pkg{\name}}
\begin{document}
  \DisableImplementation

  \DocInput{\jobname.dtx}
  \DocInput{\jobname-vi.dtx}

  \EnableImplementation
  \DisableDocumentation
  \DocInputAgain
  \PrintChanges
  \PrintIndex
\end{document}
%</driver>
% \fi
%
% \begin{documentation}
% \title{\pkgname.sty: 华中科技大学视觉标识汇编}
% \author
%   {
%     黄宇希 Huang Yuxi^^A
%     \thanks{
%       \textit{Huang} is his surname.
%     }
%     <^^A
%     \href
%       {mailto:hustvisual@hyxi.dev}
%       {hustvisual@hyxi.dev}^^A
%     >
%   }
% \date{2025-05-07 \quad Version 1.0.0} 
%
% \maketitle
%
% \tableofcontents
%
% \changes{v1.0}{2025-05-06}{Initial release.}
%
% \section{宏包介绍}
%
% 本宏包提供了华中科技大学视觉标识（visual identity）定义的接口，
% 预设了部分常用的视觉标识，
% 使得用户可以便捷地在文档中使用。
%
% \subsection{\pkgname{} 发行版本号\label{sec:version}}
%
% 更新版本往往会带来新功能和修复问题，
% 但有时也会不可避免地带来不向后兼容的修改。
% 为了清晰地传达版本之间的变化，
% 本宏包发行的版本号使用类似但不完全同于语义化版本控制（Semantic Versioning）规范
% \footnote{\url{https://semver.org/}}用以标识。
% 在本宏包中，对于版本号 |MAJOR.MINOR.PATCH|，递增相应的部分所表示的含义如下：
% \begin{itemize}
%   \item |MAJOR|：递增大版本号，
%     表示已在正文文档化的公开接口上存在不向后兼容（backward compatibility）的修改，
%     一般对文档代码不修改无法正常编译；
%   \item |MINOR|：递增小版本号，
%     表示已在正文文档化的非实验性公开接口上\emph{不}存在不向后兼容编译的修改，
%     但在实验性公开接口上存在不向后兼容的修改。
%     一般对文档代码不作修改或者只需小幅修改就可以正常编译；
%   \item |PATCH|：递增补丁版本号，
%     表示新版本含有向后兼容的 bug 修复，新功能，或新的视觉标识，
%     其中未文档化的私有接口可能会发生变化。
% \end{itemize}
% 以上内容所指的“公开接口”仅包括第 \ref{sec:usage} 节中介绍的供终端用户直接使用的接口。
% 用户在更新宏包时，可以根据版本号的变化以及更新日志来判断是否需要修改自己的文档。
%
% \section{开发说明\label{sec:dev}}
%
% 本节介绍了宏包的开发和维护相关信息，
% 包括如何添加新的色彩和图案。
% 本节内容的指令仅可在本宏包或者子模块中使用，
% 在正文文档中使用会导致编译错误。
%
% \subsection{添加新的色彩}
%
% \begin{function}{\@@_set_color:nnn}
%   \begin{syntax}
%     \cs{@@_set_color:nnn} \marg{色彩名称} \marg{色彩模型} \marg{色彩值}
%   \end{syntax}
%   \cs{@@_set_color:nnn} 是一个用于同时定义 \pkg{l3color} 和 \pkg{xcolor} 中的色彩的函数。例如：
%   \begin{verbatim}
%     \@@_set_color:nnn { hustblue } { CMYK } { 100, 74, 27, 0 }
%   \end{verbatim}
%   它包括三个必选参数：色彩名称、色彩模型和色彩值：
%   \begin{arguments}
%   \item[\marg{色彩名称}] 色彩名称，必须是一个合法的 \pkg{xcolor} 色彩名称。
%   \item[\marg{色彩模型}] 色彩模型，支持的色彩模型包括 \opt{CMYK}、\opt{cmyk}、\opt{RGB}、\opt{rgb} 等。其中 \opt{CMYK} 是本宏包新增的色彩模型，支持 0--100 范围的 \opt{cmyk} 色彩。
%   \item[\marg{色彩值}] 色彩值，支持由逗号分隔的色彩值，格式包括 \opt{CMYK}、\opt{cmyk}、\opt{RGB}、\opt{rgb} 等。
% \end{arguments}
% \end{function}
%
% \subsection{添加新的图案}
%
% 推荐使用 Inkscape 打开图案矢量图形文件，
% 并使用 svg2tikz （\url{https://github.com/xyz2tex/svg2tikz}）插件将其转换为 TikZ 代码。
% 在导出时，选择 \TeX template 为 Tikzpicture，启用裁切 Crop，关闭自动换行 Wrap paths 和缩进选项 Indent group ，数字精度 Number of decimal 设置为 3；使用 cm 为单位，关闭 Inkscape origin 选项，缩放比例 Scale 设置为 1.0。
%
% 导出后请使用 |scripts/tikz-format.pl| 脚本进行格式化，
% 脚本会对 \TikZ 代码进行格式化，包括缩进、换行、删除多余的空格等操作。
%
% 之后请手动将颜色按照一定顺序替换为如 \cs{l_@@_color_arg_i_tl} 形式的变量，
% 以便于后续的色彩参数传递。
% 在完全替换后，
% 删除开头的 |\definecolor| 语句，
% 将其 \TikZ 代码放入 guard （|%<*xxx>| 至 |%</xxx>|）中，
% 并更新相应文档，实现和 |hustvisual.ins| 文件。
%
% \begin{function}{\@@_set_vi:n}
%   \begin{syntax}
%     \cs{@@_set_vi:n} \marg{图案参数}
%   \end{syntax}
%   \cs{@@_set_vi:n} 是一个用于设置图案的函数。
%   \marg{图案参数} 是一个由逗号分隔的键值对无序列表，
%   其中每个键值对的格式为 \opt{key=value}。
%   有些键值对是可选的，如果没有设置，则使用默认值；而有些是必选的，不设置则会导致编译错误。
%   其中键值对的定义如下：
%   \begin{arguments}
%   \item[\opt{dept}] 视觉标识的所属学院，默认值为 \opt{vi}，即华中科技大学校级的视觉标识。学院的缩写使用官方网站域名四级子域名（域名 |.hust.edu.cn| 左边的部分）作为缩写。
%   \item[\opt{vi}] 视觉标识的标识符，必选参数，是一个由逗号分隔的无序列表，宏包内部会自动将其排序后存储为唯一的视觉标识名称，与和 \opt{dept} 一起作为查找图案的默认文件名。
%   \item[\opt{ncolors}] 视觉标识的色彩数量，默认值为 \opt{0}，即图案中没有可配置的色彩。
%   \item[\opt{temps}] 视觉标识的色彩预设模板，如果 \opt{ncolors} 的值大于 \opt{0}，则该参数为必选参数。色彩预设模板的格式为有序列表 \opt{\{temp1=\{color1, color2, ...\}, temp2=\{color3, color1, ...\}, ...\}}。其中 \opt{temp1}、\opt{temp2} 等为色彩预设模板的名称，\opt{color1}、\opt{color2} 等为色彩名称，色彩名称需要由 \pkg{xcolor} 宏包定义的色彩名称，且列表中的色彩数量需要等同于 \opt{ncolors} 的值。其中第一个色彩预设模板会被用作默认的色彩预设模板。
%   \item[\opt{filename}] 视觉标识的文件名，默认缺省，使用由 \opt{dept} 和 \opt{vi} 生成的文件名。如果 \opt{filename} 的值不为空，则该图案会被使用由 \opt{filename} 设置的文件名。
%   \item[\opt{aliases}] 视觉标识的别名，默认为空，即没有别名。别名的格式为有序列表 \opt{\{\{vi1,vi2\},\{vi2,vi3,vi4\},...\}}，其中 \opt{vi1,vi2}、\opt{vi2,vi3,vi4} 等为别名，使用方式同 \opt{vi}，用于方便用户调用，不需要每次都输入完整的视觉标识名称。
%   \end{arguments}
% \end{function}
%
% \section{使用说明\label{sec:usage}}
%
% \begin{function}{\hustvi}
%   \begin{syntax}
%     \cs{hustvi}\oarg{通用选项}\marg{视觉标识}
%   \end{syntax}
%   \cs{hustvi} 是本宏包提供给终端用户使用最重要的一个接口，
%   一切的视觉标识都是通过这个通用接口来使用。
%   例如：
%   \marginnote{\hustvi[height=1cm,temp=red]{emblem}}
%   \begin{verbatim}
%     \hustvi[height=1cm,temp=red]{emblem}
%   \end{verbatim}
%   可以在文档中使用如左页边所示，以通用选项：高 \qty{1}{cm}、色彩预设为\opt{blue}的华中科技大学校徽。
%   其中，\marg{视觉标识}是一个由逗号分隔的无序列表，
%   列表中的每一项都是一个视觉标识中的基础元素，
%   这些元素的组合可以形成一个完整的视觉标识。
%   如果视觉标识中只有一个基础元素，
%   则可以省略逗号分隔符。
%   而\oarg{通用选项}是由一系列逗号分隔的键值对无序列表组成的可选参数，
%   所有的视觉标识都实现了如下的通用选项：
%   \begin{arguments}
%   \item[\opt{filename}] 视觉标识的文件名，默认缺省，通常情况下不需要设置，仅在需要覆盖原有文件时使用。
%   \item[\opt{dept}] 视觉标识的所属学院，默认值为 \opt{vi}，即华中科技大学校级的视觉标识。学院的缩写使用官方网站域名四级子域名（域名 |.hust.edu.cn| 左边的部分）作为缩写。
%   \item[\opt{width}] 视觉标识的宽度，默认值为 \opt{0pt}，即使用默认的宽度。如果仅设置了宽度而没有设置高度，则高度会自动按比例缩放；如果同时设置了宽度和高度，则宽高比会被强制为 \opt{width}:\opt{height}。
%   \item[\opt{height}] 视觉标识的高度，默认值为 \opt{0pt}，效果同上。
%   \item[\opt{temp}] 视觉标识的色彩预设模板，不同视觉标识的色彩预设模板不同，具体的色彩预设模板请参考对应视觉标识的文档。
%   \item[\opt{colors}] 手动按照顺序覆写色彩预设模板，同时设置了 \opt{temp} 和 \opt{colors} 时，\opt{colors} 会覆盖 \opt{temp} 的设置。 \opt{colors} 的格式为有序列表 \opt{\{color1, color2, ...\}}，其中 \opt{color1}、\opt{color2} 等为色彩名称，色彩名称需要由 \pkg{xcolor} 宏包定义的色彩名称，且列表中的色彩数量不能超过预设模板中的色彩数量。\marginnote{\hustvi[colors={hustblue,black},temp=red,height=1cm]{emblem}} 例如：\cs{hustvi}\opt{\[colors=\{hustblue,black\},temp=red\]\{emblem\}} （如左页边所示）就是基于 \opt{red} 模板的校徽，对前两种颜色依序覆写了华科蓝 \opt{hustblue} 和黑色 \opt{black} 两种色彩\footnote{本错误配色示例仅用于说明，实际使用时请遵循视觉标识的色彩规范。}。
%   \item[\opt{opacity}] （实验性功能）视觉标识的透明度，默认值为 \opt{1}，即不透明。透明度的范围为 \opt{0} 到 \opt{1}，其中 \opt{0} 表示完全透明，\opt{1} 表示完全不透明。
%   \end{arguments}
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
%
% \section{\pkgname{} 实现细节}
%    \begin{macrocode}
%<@@=hustvisual>
%<*package>
%    \end{macrocode}
%
% \subsection{常量声明}
%
% \begin{macro}{\c_@@_univ_tl}
% 定义校级视觉标识的“学院” \opt{dept} 名称。
%    \begin{macrocode}
\tl_const:Nn \c_@@_univ_tl { vi }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\c_@@_depts_clist}
% 定义了各个学院的缩写，使用官方网站域名四级子域名（域名 |.hust.edu.cn| 左边的部分）作为缩写。
% 如遇类似同济医学院下设药学院（|pharm.tjmu.edu.cn|）或第一临床学院（|whuh.com|）的以非华科域名结尾的学院，另行商议。
%    \begin{macrocode}
\clist_const:Ne \c_@@_depts_clist
  {
    \c_@@_univ_tl,
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\c_@@_nargs_int, \c_@@_args_clist}
% 参数索引。如有需要在这里修改参数索引数量。
%    \begin{macrocode}
\int_const:Nn \c_@@_nargs_int { 5 }
\clist_new:N \c_@@_args_clist
\int_step_inline:nn { \c_@@_nargs_int }
  {
    \exp_args:NNe \clist_put_right:Nn \c_@@_args_clist
      {
        \int_to_roman:n { #1 }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{变量声明}
% \begin{macro}{
%   \l_@@_color_arg_i_tl,
%   \l_@@_color_arg_ii_tl,
%   \l_@@_color_arg_iii_tl,
%   \l_@@_color_arg_iv_tl,
%   \l_@@_color_arg_v_tl,
% }
% 传入 \TikZ 中的色彩参数，默认为黑色。
%    \begin{macrocode}
\clist_map_inline:Nn \c_@@_args_clist
  {
    \tl_new:c { l_@@_color_arg_ #1 _tl }
    \tl_set:cn { l_@@_color_arg_ #1 _tl } { black }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\l_@@_color_args_clist}
% 色彩参数列表。
%    \begin{macrocode}
\clist_new:N \l_@@_color_args_clist
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{
%   \l_@@_dept_tl,
%   \l_@@_vi_clist,
%   \l_@@_ncolors_int,
%   \l_@@_temps_prop,
%   \l_@@_temp_tl,
%   \l_@@_filename_tl,
%   \l_@@_aliases_clist,
%   \l_@@_colors_clist,
%   \l_@@_vi_tl,
%   \l_@@_width_dim,
%   \l_@@_height_dim,
%   \l_@@_opacity_fp,
% }
% 视觉标识临时变量。
%    \begin{macrocode}
\tl_new:N \l_@@_dept_tl
\clist_new:N \l_@@_vi_clist
\int_new:N \l_@@_ncolors_int
\prop_new:N \l_@@_temps_prop
\tl_new:N \l_@@_temp_tl
\tl_new:N \l_@@_filename_tl
\clist_new:N \l_@@_aliases_clist
\clist_new:N \l_@@_colors_clist
\tl_new:N \l_@@_vi_tl
\dim_new:N \l_@@_width_dim
\dim_new:N \l_@@_height_dim
\fp_new:N \l_@@_opacity_fp
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\g_@@_vi_prop}
% 视觉标识属性列表。
%    \begin{macrocode}
\prop_new:N \g_@@_vi_prop
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{辅助函数}
%
% \begin{macro}{
%   \@@_msg_new:nn,
%   \@@_warning:n,
%   \@@_warning:ne,
%   \@@_warning:nee,
%   \@@_warning:neee,
%   \@@_error:n,
%   \@@_error:ne,
%   \@@_error:nee,
%   \@@_error:neee,
%}
% 各种信息函数的缩略形式。
%    \begin{macrocode}
\cs_new:Npn \@@_msg_new:nn { \msg_new:nnn { hustvisual } }
\cs_new:Npn \@@_warning:n { \msg_warning:nn { hustvisual } }
\cs_new:Npn \@@_warning:ne { \msg_warning:nne { hustvisual } }
\cs_new:Npn \@@_warning:nee { \msg_warning:nnee { hustvisual } }
\cs_new:Npn \@@_warning:neee { \msg_warning:nneee { hustvisual } }
\cs_new:Npn \@@_error:n { \msg_error:nn { hustvisual } }
\cs_new:Npn \@@_error:ne { \msg_error:nne { hustvisual } }
\cs_new:Npn \@@_error:nee { \msg_error:nnee { hustvisual } }
\cs_new:Npn \@@_error:neee { \msg_error:nneee { hustvisual } }
%    \end{macrocode}
% \end{macro}
%
% \subsection{宏包载入}
%
%    \begin{macrocode}
\RequirePackage{tikz}
\RequirePackage{xcolor}
%    \end{macrocode}
%
% \subsection{内部函数}
%
% \begin{macro}{\@@_deploy_colors:}
% 将 \cs{l_@@_color_args_clist} 展开到对应的变量方便在视觉标识文件（|hustvisual-*.def|）中调用。
%    \begin{macrocode}
\@@_msg_new:nn { color-args-exceed }
{
  The~ `colors'~ arguments(#1)~ exceed~ the~ number~ of~ defined~ colors(#2).
  Please~ check~ the~ number~ of~ colors~ in~ the~ documentation~ of~ the~ package.
}
\int_new:N \l_@@_color_nargs_int
\cs_new:Npn \@@_deploy_colors:
  {
    \int_set:Nn \l_@@_color_nargs_int
      { \clist_count:N \l_@@_color_args_clist }
    \int_compare:nNnTF
      { \l_@@_color_nargs_int } > { \c_@@_nargs_int }
      {
        \@@_warning:nee { color-args-exceed }
          { \int_use:N \l_@@_color_nargs_int }
          { \int_use:N \c_@@_nargs_int }
        \@@_deploy_colors:N \c_@@_nargs_int
      }
      {
        \@@_deploy_colors:N \l_@@_color_nargs_int
      }
  }
\tl_new:N \l_@@_color_arg_tl
\cs_new:Npn \@@_deploy_colors:N #1
  {
    \int_step_inline:nn { #1 }
      {
        \tl_set:Nx \l_@@_color_arg_tl
          {
            l_@@_color_arg_
            \clist_item:Nn \c_@@_args_clist { ##1 }
            _tl
          }
        \tl_set:cx
          {
            \l_@@_color_arg_tl
          }
          {
            \clist_item:Nn \l_@@_color_args_clist { ##1 }
          }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_sort_vi_name:, \@@_sort_vi_name:N}
% 对 \cs{l_@@_vi_clist} 进行排序。
%    \begin{macrocode}
\cs_new:Npn \@@_sort_vi_name:
  {
    \@@_sort_vi_name:N \l_@@_vi_clist
  }
\cs_new:Npn \@@_sort_vi_name:N #1
  {
    \clist_sort:Nn #1
      {
        \str_compare:nNnTF { ##1 } > { ##2 }
        { \sort_return_swapped: }
        { \sort_return_same: }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_vi_name:, \@@_vi_name:N, \@@_vi_name:NN}
% 从 \cs{l_@@_dept_tl}，和 \cs{l_@@_vi_clist} 中生成唯一的视觉标识名称。
%    \begin{macrocode}
\tl_const:Nn \c_@@_dept_sep_tl { - }
\tl_const:Nn \c_@@_vi_sep_tl { - }
\cs_new:Npn \@@_vi_name:
  {
    \@@_vi_name:N \l_@@_vi_clist
  }
\cs_new:Npn \@@_vi_name:N #1
  {
    \@@_vi_name:NN \l_@@_dept_tl #1
  }
\cs_new:Npn \@@_vi_name:NN #1#2
  {
    \tl_use:N #1
    \tl_use:N \c_@@_dept_sep_tl
    \exp_args:NNV \clist_use:Nn #2 \c_@@_vi_sep_tl
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_vi_filename:}
% 生成视觉标识文件名。
%    \begin{macrocode}
\tl_const:Nn \c_@@_vi_filename_prefix_tl { hustvisual- }
\tl_const:Nn \c_@@_vi_filename_suffix_tl { .def }
\cs_new:Npn \@@_vi_filename:
  {
    \tl_use:N \c_@@_vi_filename_prefix_tl
    \@@_vi_name:
    \tl_use:N \c_@@_vi_filename_suffix_tl
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_prop_default_value:N}
% 定义属性的默认值为第一个插入的值。
%    \begin{macrocode}
%\bool_new:N \l_@@_prop_set_bool
\tl_new:N \l_@@_prop_set_tl
\cs_new:Npn \@@_prop_default_value:N #1
  {
    \bool_set_false:N \l_@@_prop_set_bool
%    \end{macrocode}
% \cs{prop_map_break:} 因未知原因无法使用。
%    \begin{macrocode}
    \prop_map_inline:Nn #1
      {
        \bool_if:NF \l_@@_prop_set_bool
          {
            \bool_set_true:N \l_@@_prop_set_bool
            \tl_set:Nn \l_@@_prop_set_tl { ##2 }
          }
      }
    \tl_use:N \l_@@_prop_set_tl
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\keys_define:nn { hustvisual }
  {
    dev .meta:nn = { hustvisual / dev } { #1 },
    user .meta:nn = { hustvisual / user } { #1 },
  }
%    \end{macrocode}
%
% \subsection{子模块接口}
%
% \subsubsection{色彩定义}
%
% \begin{macro}{\@@_set_color:nnn}
% 定义色彩的函数。同时定义了 \pkg{l3color} 和 \pkg{xcolor} 中的色彩。
% 此外，新增了 \opt{CMYK} 色彩模型的支持，用于添加 0--100 范围的 \opt{cmyk} 色彩。
% \begin{arguments}
%   \item 色彩名称
%   \item 色彩模型，如 \opt{CMYK}(0--100)、\opt{cmyk}(0--1)、\opt{RGB}(0--255)、\opt{rgb}(0--1) 等
%   \item 色彩值，用逗号分隔的数值
% \end{arguments}
%    \begin{macrocode}
\seq_new:N \l_@@_color_models_seq
\seq_new:N \l_@@_color_values_seq
\int_new:N \l_@@_set_colors_int
\tl_new:N \l_@@_color_model_tl
\tl_new:N \l_@@_color_models_tl
\tl_new:N \l_@@_color_values_tl
\clist_new:N \l_@@_set_colors_clist
\cs_new:Npn \@@_set_color:nnn #1#2#3
  {
    \seq_set_split:Nnn \l_@@_color_models_seq { / } { #2 }
    \seq_set_split:Nnn \l_@@_color_values_seq { / } { #3 }
    \int_compare:nNnF
      { \seq_count:N \l_@@_color_models_seq }
      =
      { \seq_count:N \l_@@_color_values_seq }
      {
        \@@_error:nee { color-models-unpair }
          { \seq_count:N \l_@@_color_models_seq }
          { \seq_count:N \l_@@_color_values_seq }
      }
    \exp_args:NNe \int_set:Nn \l_@@_set_colors_int
      { \seq_count:N \l_@@_color_models_seq }
    \int_step_inline:nn { \l_@@_set_colors_int } % ##1
      {
        \tl_set:Ne \l_@@_color_model_tl
          { \seq_item:Nn \l_@@_color_models_seq { ##1 } }
        \exp_args:Nne \str_if_eq:nnT { CMYK }
          { \seq_item:Nn \l_@@_color_models_seq { ##1 } }
          {
            \clist_clear:N \l_@@_set_colors_clist
            \seq_set_item:Nnn \l_@@_color_models_seq { ##1 } { cmyk }
            \exp_args:Ne \clist_map_inline:nn % ####1
              { \seq_item:Nn \l_@@_color_values_seq { ##1 } }
              {
                \clist_put_right:Ne \l_@@_set_colors_clist
                  { \fp_to_decimal:n { \fp_eval:n { ####1 / 100 } } }
              }
            \exp_args:NNnV \seq_set_item:Nnn
              \l_@@_color_values_seq { ##1 } \l_@@_set_colors_clist
          }
      }
    \tl_set:Ne \l_@@_color_models_tl
      { \seq_use:Nn \l_@@_color_models_seq { / } }
    \tl_set:Ne \l_@@_color_values_tl
      { \seq_use:Nn \l_@@_color_values_seq { / } }
    \exp_args:Nnee \color_set:nnn { #1 }
      { \l_@@_color_models_tl }
      { \l_@@_color_values_tl }
    \definecolor { #1 }
      { \l_@@_color_models_tl }
      { \l_@@_color_values_tl }
  }
\@@_msg_new:nn { color-models-unpair }
  {
    The~ number(#1)~ of~ color~ models~ in~ the~ `colors'~
    arguments~ is~ not~ equal~ to~ the~ number(#2)~ of~ color values.
  }
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{图案定义}
%
% \begin{macro}{\@@_set_vi:n}
% 定义视觉标识图案的函数。
%    \begin{macrocode}
\cs_new:Npn \@@_set_vi:n #1
  {
    \group_begin:
    \keys_set:nn { hustvisual / dev } { #1 }
    \@@_process_set_vi:
    \group_end:
  }
%\prop_new:N \l_@@_colors_clist
\keys_define:nn { hustvisual / dev }
  {
    dept .choices:Vn = \c_@@_depts_clist
      {
        \tl_set_eq:NN \l_@@_dept_tl \l_keys_choice_tl
      },
    dept .initial:V = \c_@@_univ_tl,
    vi .clist_set:N = \l_@@_vi_clist,
    vi .value_required:n = true,
    ncolors .int_set:N = \l_@@_ncolors_int,
    ncolors .initial:V = \c_zero_int,
    temps .meta:nn = { hustvisual / dev / temps } { #1 },
    temps / unknown .code:n =
      {
        \clist_set:Nn \l_@@_colors_clist { #1 }
        \prop_put:NVV \l_@@_temps_prop \l_keys_key_str \l_@@_colors_clist
      },
    filename .tl_set:N = \l_@@_filename_tl,
    filename .initial:V = \c_empty_tl,
    aliases .clist_set:N = \l_@@_aliases_clist,
    aliases .initial:V = \c_empty_clist,
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_process_set_vi:}
% 处理在定义视觉标识图案时传入的参数。
%    \begin{macrocode}
\prop_new:N \l_@@_vi_prop
\int_new:N \l_@@_ncolors_tmp_int
\clist_new:N \l_@@_alias_name_clist
\tl_new:N \l_@@_alias_name_tl
\cs_new:Npn \@@_process_set_vi:
  {
    \prop_clear:N \l_@@_vi_prop
    \int_compare:nNnT
      { \l_@@_ncolors_int } > { \c_@@_nargs_int }
      {
        \@@_error:nee { colors-exceed-max }
          { \int_use:N \l_@@_ncolors_int }
          { \int_use:N \c_@@_nargs_int }
      }
    \prop_put:NnV \l_@@_vi_prop { ncolors } \l_@@_ncolors_int
    \prop_map_inline:Nn \l_@@_temps_prop
      {
        \int_set:Nn \l_@@_ncolors_tmp_int
          { \clist_count:n { ##2 } }
        \int_compare:nNnF
          { \l_@@_ncolors_int } = { \l_@@_ncolors_tmp_int }
          {
            \@@_error:neee { colors-not-match }
              { ##1 }
              { \int_use:N \l_@@_ncolors_tmp_int }
              { \int_use:N \l_@@_ncolors_int }
          }
      }
    \int_compare:nNnF
      { \l_@@_ncolors_int } = { \c_zero_int }
      {
        \int_compare:nNnT
          { \prop_count:N \l_@@_temps_prop } = { \c_zero_int }
          {
            \@@_error:n { no-temp }
          }
      }
    \prop_put:NnV \l_@@_vi_prop { temps } \l_@@_temps_prop
    \@@_sort_vi_name:
    \tl_if_empty:NT \l_@@_filename_tl
      {
        \tl_set:Ne \l_@@_filename_tl
          { \@@_vi_filename: }
      }
    \file_if_exist:VF \l_@@_filename_tl
      {
        \@@_warning:nee { filename-error }
          { \tl_use:N \l_@@_filename_tl }
          { \@@_vi_name: }
      }
    \prop_put:NnV \l_@@_vi_prop { filename } \l_@@_filename_tl
    \prop_if_in:NeT \g_@@_vi_prop { \@@_vi_name: }
      {
        \@@_warning:ne { vi-skip }
          { \@@_vi_name: }
      }
    \prop_gput_if_not_in:NeV \g_@@_vi_prop \@@_vi_name: \l_@@_vi_prop
    \clist_map_variable:NNn \l_@@_aliases_clist \l_@@_alias_name_clist
      {
        \prop_clear:N \l_@@_vi_prop
        \prop_put:Nne \l_@@_vi_prop { source } { \@@_vi_name: }
        \tl_set:Ne \l_@@_alias_name_tl
          { \@@_vi_name:N \l_@@_alias_name_clist }
        \prop_if_in:NVT \g_@@_vi_prop \l_@@_alias_name_tl
          {
            \@@_warning:nee { vi-skip }
              { \l_@@_alias_name_tl }
          }
        \prop_gput_if_not_in:NVV \g_@@_vi_prop
          \l_@@_alias_name_tl
          \l_@@_vi_prop
      }
  }
\@@_msg_new:nn { colors-exceed-max }
  {
    The~ number(#1)~ of~ colors~ in~ the~ `ncolors'~ property~
    exceeds~ the~ maximum~ number(#2)~ of~ colors.~
    Please~ increase~ the~ number~ of~ colors~ in~ the~ \c_@@_nargs_int.
  }
\@@_msg_new:nn { no-temp }
  {
    The~ `temps'~ property~ should~ be~ set~ to~ a~ list~ of~ colors,~
    when~ the~ `ncolors'~ property~ is~ not~ zero.
  }
\@@_msg_new:nn { colors-not-match }
  {
    The~ number(#2)~ of~ colors~ in~ the~ `temps'~ property(#1)~
    does~ not~ match~ the~ number(#3)~ asserted~ in~ the~
    `ncolors'~ property.
  }
\@@_msg_new:nn { filename-error }
  {
    The~ filename~(#1)~ of~ the~ vi(#2)~
    is~ not~ found~ in~ the~ TeX~ search~ path.~
    Please~ check~ the~ filename.
  }
\@@_msg_new:nn { vi-skip }
  {
    The~ vi~(#1)~ is~ already~ defined.~
    The~ new~ definition~ has~ been~ skipped.
  }
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{用户接口}
%
% \begin{macro}{\hustvi}
% 插入视觉标识图案的主函数。
%    \begin{macrocode}
\NewDocumentCommand \hustvi { O{} m }
  {
    \group_begin:
    \keys_set:nn { hustvisual / user }
      {
        #1,
        vi = { #2 },
      }
    \@@_process_vi_name:
    \@@_process_temp:
    \@@_process_colors:
    \@@_process_file:
    \@@_process_vi:
    \group_end:
  }
\keys_define:nn { hustvisual / user }
  {
    dept .choices:Vn = \c_@@_depts_clist
      {
        \tl_set_eq:NN \l_@@_dept_tl \l_keys_choice_tl
      },
    vi .clist_set:N = \l_@@_vi_clist,
    vi .value_required:n = true,
    filename .tl_set:N = \l_@@_filename_tl,
    filename .initial:V = \c_empty_tl,
    width .dim_set:N = \l_@@_width_dim,
    width .initial:V = \c_zero_dim,
    height .dim_set:N = \l_@@_height_dim,
    height .initial:V = \c_zero_dim,
    temp .tl_set:N = \l_@@_temp_tl,
    temp .initial:V = \c_empty_tl,
    colors .clist_set:N = \l_@@_colors_clist,
    colors .initial:V = \c_empty_clist,
    opacity .fp_set:N = \l_@@_opacity_fp,
    opacity .initial:V = \c_one_fp,
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_process_vi_name:}
% 处理视觉标识唯一名称以及别名的函数。
%    \begin{macrocode}
\tl_new:N \l_@@_source_name_tl
\cs_new:Npn \@@_process_vi_name:
  {
    \@@_sort_vi_name:
    \prop_get:NeNF \g_@@_vi_prop \@@_vi_name: \l_@@_vi_prop
      {
        \@@_error:nee { invalid-vi-name }
          { \l_@@_dept_tl }
          { \l_@@_vi_clist }
      }
    \prop_get:NnNT \l_@@_vi_prop { source } \l_@@_source_name_tl
      {
        \prop_get:NVN \g_@@_vi_prop
          \l_@@_source_name_tl
          \l_@@_vi_prop
      }
  }
\@@_msg_new:nn { invalid-vi-name }
  {
    The~ combination~ of~ `dept'(#1)~ and~ `vi'(#2)~
    is~ not~ valid.~
    Please~ check~ the~ documentation~ of~ the~ package.
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_process_temp:}
% 处理视觉标识色彩预设模板的函数。
%    \begin{macrocode}
\bool_new:N \l_@@_prop_set_bool
\cs_new:Npn \@@_process_temp:
  {
    \prop_get:NnN \l_@@_vi_prop { temps } \l_@@_temps_prop
    \prop_get:NVNF \l_@@_temps_prop
      \l_@@_temp_tl \l_@@_color_args_clist
      {
        \tl_if_empty:NF \l_@@_temp_tl
          {
            \@@_warning:ne { invalid-temp }
              { \l_@@_temp_tl }
          }
        \bool_set_false:N \l_@@_prop_set_bool
        \prop_map_inline:Nn \l_@@_temps_prop
          {
            \bool_if:NF \l_@@_prop_set_bool
              {
                \bool_set_true:N \l_@@_prop_set_bool
                \clist_set:Nn \l_@@_color_args_clist { ##2 }
              }
          }
      }
    \@@_deploy_colors:
  }
\@@_msg_new:nn { invalid-temp }
  {
    The~ `temp'~ property~(#1)~ is~ not~ valid.~
    The~ default~ template~ will~ be~ used.~
    Please~ check~ the~ documentation~ of~ the~ package.
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_process_colors:}
% 处理视觉标识图案覆写色彩的函数。
%    \begin{macrocode}
\tl_new:N \l_@@_color_tl
\cs_new:Npn \@@_process_colors:
  {
    \clist_if_empty:NF \l_@@_colors_clist
      {
        \clist_set_eq:NN \l_@@_color_args_clist \l_@@_colors_clist
        \@@_deploy_colors:
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_process_file:}
% 读取视觉标识文件（|hustvisual-*.def|），并将其内容前后添加 \TikZ 环境。
%    \begin{macrocode}
\cs_new:Npn \@@_process_file:
  {
    \tl_if_empty:NT \l_@@_filename_tl
      {
        \prop_get:NnN \l_@@_vi_prop { filename } \l_@@_filename_tl
      }
    \file_get:VnNF \l_@@_filename_tl { \ExplSyntaxOn } \l_@@_vi_tl
      {
        \@@_error:ne { file-not-found }
          { \tl_use:N \l_@@_filename_tl }
      }
    \tl_gput_left:Nn \l_@@_vi_tl
      {
        \begin{tikzpicture}[
          inner~sep=0pt,
          outer~sep=0pt,
          opacity=\fp_use:N \l_@@_opacity_fp
        ]
      }
    \tl_gput_right:Nn \l_@@_vi_tl
      {
        \end{tikzpicture}
        \color_fill:n {red}
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_process_vi:}
% 处理视觉标识图案尺寸的函数。
%    \begin{macrocode}
\box_new:N \l_@@_vi_box
\cs_new:Npn \@@_process_vi:
  {
    \exp_args:NNV \hbox_set:Nn \l_@@_vi_box \l_@@_vi_tl
    \dim_compare:nNnTF
      { \l_@@_width_dim } > { \c_zero_dim }
      {
        \dim_compare:nNnTF
        { \l_@@_height_dim } > { \c_zero_dim }
        {
          \exp_args:NNVV \box_resize_to_wd_and_ht:Nnn \l_@@_vi_box
            \l_@@_width_dim \l_@@_height_dim
        }
        {
          \exp_args:NNV \box_resize_to_wd:Nn \l_@@_vi_box \l_@@_width_dim
        }
      }
      {
        \dim_compare:nNnT
        { \l_@@_height_dim } > { \c_zero_dim }
        {
          \exp_args:NNV \box_resize_to_ht:Nn \l_@@_vi_box \l_@@_height_dim
        }
      }
    \box_use:N \l_@@_vi_box
  }
\@@_msg_new:nn { file-not-found }
  {
    The~ file~(#1)~ is~ not~ found.~
    Please~ check~ the~ file~ name.
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
% \subsection{文档样式}
%    \begin{macrocode}
%<*doc-sty>
%    \end{macrocode}
%
% 解决 |Package multicol Error: Error saving partial page.|
% 方法来自于 \url{https://tex.stackexchange.com/a/95893}。
%    \begin{macrocode}
\setlength\IndexMin{100pt}
%    \end{macrocode}
%
% \begin{macro}[no-user-doc]{\TikZ}
%    \begin{macrocode}
\newcommand\TikZ{Ti\emph{k}Z}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[no-user-doc]{\key}
% 用于在文档中输出自定义索引的命令，主要用于键值对的键的索引。仅当索引项的父分类为 |hustvi| 时，即用于文档类选项时，隐藏父分类。
%  \begin{arguments}
%    \item 在索引中显示项的父分类，默认为 \opt{hustvi}。
%    \item 命令本体。
%  \end{arguments}
%    \begin{macrocode}
\DeclareDocumentCommand \key { O{hustvi} m }
  {
    \tl_if_eq:nnTF { #1 } { hustvi }
      { \cmd[module=#1/]{#2} }
      { \cmd[module=#1/]{#1/#2} }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[no-user-doc]{\opt}
% 输出键值对的值。
%    \begin{macrocode}
\DeclareDocumentCommand \opt { s m }
  { \IfBooleanTF {#1} { \texttt{\bfseries \upshape #2} } { \texttt{\upshape #2} } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\g_@@_show_vi_bool}
% 定义是否显示视觉标识实现的全局变量，默认为不显示。
%    \begin{macrocode}
\bool_new:N \g_@@_show_vi_bool
\bool_gset_false:N \g_@@_show_vi_bool
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{viimplementation}
% 定义实现视觉标识所需要的文档环境。
%    \begin{macrocode}
\NewDocumentEnvironment { viimplementation } { }
  {
    \bool_if:NF \g_@@_show_vi_bool { \comment }
  }
  {
    \bool_if:NF \g_@@_show_vi_bool { \endcomment }
  }
%    \end{macrocode}
% \end{environment}
%
%    \begin{macrocode}
%</doc-sty>
%    \end{macrocode}
%
% \section{子模块实现细节}
%
% \end{implementation}
