% Copyright 2026 Open-Guji (https://github.com/open-guji) % % Licensed under the Apache License, Version 2.0 (the "License"); % you may not use this file except in compliance with the License. % You may obtain a copy of the License at % % http://www.apache.org/licenses/LICENSE-2.0 % % Unless required by applicable law or agreed to in writing, software % distributed under the License is distributed on an "AS IS" BASIS, % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % See the License for the specific language governing permissions and % limitations under the License. % luatex-cn-textbox.sty % TextBox support for vertical typesetting % This is a subpackage of luatex_cn % % NOTE: This file must be loaded AFTER luatexcn/vertical keys are defined % \RequirePackage{core/luatex-cn-core-base} \RequirePackage{expl3} \RequirePackage{xparse} \ProvidesExplPackage {core/luatex-cn-core-textbox} {2026/08/07} {0.4.1} {TextBox Support for Vertical Typesetting} % Grid Textbox Command (Simplified for Single Column) % Syntax: \GridTextbox[height=N, fill=true/false]{content} % height is in grid units (integers), width is always 1 % Key-value interface for \GridTextbox \bool_new:N \l__luatexcn_textbox_border_bool \tl_new:N \l__luatexcn_textbox_box_align_tl \tl_new:N \l__luatexcn_textbox_inner_gw_tl \tl_new:N \l__luatexcn_textbox_inner_gh_tl \dim_new:N \l__luatexcn_textbox_inner_gw_dim \dim_new:N \l__luatexcn_textbox_inner_gh_dim \bool_new:N \l__luatexcn_textbox_floating_bool \bool_new:N \l__luatexcn_textbox_transparent_bool \tl_new:N \l__luatexcn_textbox_x_tl \tl_new:N \l__luatexcn_textbox_y_tl \tl_new:N \l__luatexcn_textbox_bg_color_tl \tl_new:N \l__luatexcn_textbox_font_color_tl \tl_new:N \l__luatexcn_textbox_bg_rgb_tl \tl_new:N \l__luatexcn_textbox_font_rgb_tl \tl_new:N \l__luatexcn_textbox_font_size_tl \tl_new:N \l__luatexcn_textbox_floating_paper_width_tl \tl_new:N \l__luatexcn_textbox_border_shape_tl \tl_new:N \l__luatexcn_textbox_border_color_tl \tl_new:N \l__luatexcn_textbox_border_width_tl \tl_new:N \l__luatexcn_textbox_border_margin_tl \tl_new:N \l__luatexcn_textbox_border_margin_x_tl \tl_new:N \l__luatexcn_textbox_border_margin_y_tl \tl_new:N \l__luatexcn_textbox_outer_margin_tl \tl_new:N \l__luatexcn_textbox_border_rgb_tl \bool_new:N \l__luatexcn_textbox_outer_border_bool \tl_new:N \l__luatexcn_textbox_outer_border_thickness_tl \tl_new:N \l__luatexcn_textbox_outer_border_sep_tl \tl_new:N \l__luatexcn_textbox_padding_top_tl \tl_new:N \l__luatexcn_textbox_padding_bottom_tl \keys_define:nn { luatexcn / textbox } { height .tl_set:N = \l__luatexcn_textbox_height_tl, height .initial:n = 0, n-cols .int_set:N = \l__luatexcn_textbox_n_cols_int, n-cols .initial:n = 0, outer-cols .int_set:N = \l__luatexcn_textbox_outer_cols_int, outer-cols .initial:n = 0, fill .meta:n = { box-align = fill }, box-align .tl_set:N = \l__luatexcn_textbox_box_align_tl, box-align .initial:n = {top}, border .bool_set:N = \l__luatexcn_textbox_border_bool, border .initial:n = false, banxin .bool_set:N = \l__luatexcn_textbox_banxin_bool, column-align .tl_set:N = \l__luatexcn_textbox_col_align_tl, column-align .initial:n = {}, % debug key removed - use global \LtcDebugOn vertical-align .tl_set:N = \l__luatexcn_textbox_box_align_tl, floating .bool_set:N = \l__luatexcn_textbox_floating_bool, floating .initial:n = false, transparent .bool_set:N = \l__luatexcn_textbox_transparent_bool, transparent .initial:n = true, floating-paper-width .tl_set:N = \l__luatexcn_textbox_floating_paper_width_tl, floating-paper-width .initial:n = 0pt, x .tl_set:N = \l__luatexcn_textbox_x_tl, x .initial:n = 0pt, y .tl_set:N = \l__luatexcn_textbox_y_tl, y .initial:n = 0pt, background-color .tl_set:N = \l__luatexcn_textbox_bg_color_tl, background-color .initial:n = {}, font-color .tl_set:N = \l__luatexcn_textbox_font_color_tl, font-color .initial:n = {}, font-size .tl_set:N = \l__luatexcn_textbox_font_size_tl, font-size .initial:n = {}, grid-width .tl_set:N = \l__luatexcn_textbox_inner_gw_tl, grid-width .initial:n = {}, grid-height .tl_set:N = \l__luatexcn_textbox_inner_gh_tl, grid-height .initial:n = {}, % Border shape parameters (rect/octagon/circle) border-shape .tl_set:N = \l__luatexcn_textbox_border_shape_tl, border-shape .initial:n = {none}, border-color .tl_set:N = \l__luatexcn_textbox_border_color_tl, border-color .initial:n = {}, border-width .tl_set:N = \l__luatexcn_textbox_border_width_tl, border-width .initial:n = {0.4pt}, border-margin .tl_set:N = \l__luatexcn_textbox_border_margin_tl, border-margin .initial:n = {0pt}, border-margin-x .tl_set:N = \l__luatexcn_textbox_border_margin_x_tl, border-margin-x .initial:n = {}, border-margin-y .tl_set:N = \l__luatexcn_textbox_border_margin_y_tl, border-margin-y .initial:n = {}, border-offset .tl_set:N = \l__luatexcn_textbox_border_offset_tl, border-offset .initial:n = {0pt}, outer-margin .tl_set:N = \l__luatexcn_textbox_outer_margin_tl, outer-margin .initial:n = {0pt}, outer-border .bool_set:N = \l__luatexcn_textbox_outer_border_bool, outer-border .initial:n = false, outer-border-thickness .tl_set:N = \l__luatexcn_textbox_outer_border_thickness_tl, outer-border-thickness .initial:n = {1pt}, outer-border-sep .tl_set:N = \l__luatexcn_textbox_outer_border_sep_tl, outer-border-sep .initial:n = {2pt}, padding-top .tl_set:N = \l__luatexcn_textbox_padding_top_tl, padding-top .initial:n = {}, padding-bottom .tl_set:N = \l__luatexcn_textbox_padding_bottom_tl, padding-bottom .initial:n = {}, % Legacy aliases column-padding-top .tl_set:N = \l__luatexcn_textbox_padding_top_tl, column-padding-bottom .tl_set:N = \l__luatexcn_textbox_padding_bottom_tl, fill-padding-top .tl_set:N = \l__luatexcn_textbox_padding_top_tl, fill-padding-bottom .tl_set:N = \l__luatexcn_textbox_padding_bottom_tl, % Forward unknown keys: try settings first, then style unknown .code:n = { \exp_args:Nnx \keys_if_exist:nnTF { luatexcn / settings } { \l_keys_key_str } { \keys_set:nx { luatexcn / settings } { \l_keys_key_str = { \exp_not:n {#1} } } } { \exp_args:Nnx \keys_if_exist:nnTF { luatexcn / style } { \l_keys_key_str } { \keys_set:nx { luatexcn / style } { \l_keys_key_str = { \exp_not:n {#1} } } } { } } }, } \NewDocumentCommand{\textboxSetup}{ m } { \keys_set:nn { luatexcn / textbox } { #1 } } \NewDocumentCommand{\TextBox}{ O{} +m } { \group_begin: % Inherit debug setting from global environment % No local override anymore \keys_set:nn { luatexcn / textbox } { #1 } % Apply settings overrides (punct-mode etc.) via judouSetup within this group \tl_if_empty:NF \l__luatexcn_settings_punct_mode_tl { \judouSetup { punct-mode = \l__luatexcn_settings_punct_mode_tl } } % Width is always 1 for outer layout (textbox occupies 1 column externally) \setluatexattribute\cnverticaltextboxwidth{1} % Calculate inner grid width via Lua (replaces TeX-side decision tree) \dim_set:Nn \l__luatexcn_textbox_inner_gw_dim { \lua_now:e { local ~ tb = require('core.luatex-cn-core-textbox') tex.print(tostring(tb.calc_inner_grid_width({ inner_gw = \tl_if_empty:NTF \l__luatexcn_textbox_inner_gw_tl { 0 } { \dim_to_decimal_in_sp:n { \l__luatexcn_textbox_inner_gw_tl } }, column_width = \dim_to_decimal_in_sp:n { \g__luatexcn_column_current_width_dim }, outer_cols = \int_use:N \l__luatexcn_textbox_outer_cols_int, n_cols = \int_use:N \l__luatexcn_textbox_n_cols_int, content_gw = \dim_to_decimal_in_sp:n { \l__luatexcn_content_grid_width_tl }, }))) } sp } \tl_if_empty:NTF \l__luatexcn_textbox_inner_gh_tl { \dim_set:Nn \l__luatexcn_textbox_inner_gh_dim { \l__luatexcn_content_grid_height_tl } } { \dim_set:Nn \l__luatexcn_textbox_inner_gh_dim { \l__luatexcn_textbox_inner_gh_tl } } % Capture content in a box and process it via Lua for inner verticality \vbox_set:Nn \l_tmpa_box { \setluatexattribute\cnverticaltextboxwidth{0} \setluatexattribute\cnverticaltextboxheight{0} % Reset jiazhu attributes inside textbox: inner content is not textflow, % even if textbox is inside \夹注{}. Without this reset, inner glyphs % inherit ATTR_JIAZHU=1 and get sent to textflow layout, causing them to % be placed in sub-columns (horizontally) instead of stacked vertically. \setluatexattribute\cnverticaljiazhu{0} \setluatexattribute\cnverticaljiazhusub{0} \setluatexattribute\cnverticaljiazhumode{0} % Note: indent is inherited from style stack (no longer reset here) % Reset paragraph spacing to prevent unwanted glues in grid layout \dim_set:Nn \l_tmpa_dim { \l__luatexcn_content_grid_height_tl } % Scale font size \tl_if_empty:NTF \l__luatexcn_textbox_font_size_tl { % Default auto-scaling for multi-column boxes \int_compare:nNnT \l__luatexcn_textbox_n_cols_int > 1 { \dim_set:Nn \l_tmpa_dim { \l__luatexcn_textbox_inner_gw_dim * 85 / 100 } \fontsize{\l_tmpa_dim}{\l__luatexcn_textbox_inner_gw_dim}\selectfont } } { % User-specified font size \dim_set:Nn \l_tmpa_dim { \l__luatexcn_textbox_font_size_tl } \fontsize{\l_tmpa_dim}{\l_tmpa_dim}\selectfont } % Inner line length: always max — column wrapping is done by the grid % layout (col_limit = height), not by TeX's line breaker. Letting TeX % pre-break at height*grid_height splits Western words with hyphens and % misaligns columns (issue #50): TeX measures Latin letters at natural % width while the grid gives every glyph a full cell. \dim_set_eq:NN \hsize \c_max_dim \dim_set_eq:NN \hfuzz \c_max_dim \int_set:Nn \hbadness { 10000 } #2 } % Expand variables to ensure they contain the color string, not a macro name % Use o-expansion to preserve spaces (standard x-expansion strips them in ExplSyntax) \tl_set:No \l__luatexcn_textbox_bg_color_tl { \l__luatexcn_textbox_bg_color_tl } \tl_set:No \l__luatexcn_textbox_font_color_tl { \l__luatexcn_textbox_font_color_tl } % Convert background color to RGB \cs_if_exist:cTF { color @ \l__luatexcn_textbox_bg_color_tl } { \exp_args:NV \extractcolorspec \l__luatexcn_textbox_bg_color_tl \l_tmpa_tl \exp_args:NNx \convertcolorspec \l_tmpa_tl { rgb } \l_tmpb_tl \tl_set:Nx \l__luatexcn_textbox_bg_rgb_tl { \l_tmpb_tl } } { \tl_set_eq:NN \l__luatexcn_textbox_bg_rgb_tl \l__luatexcn_textbox_bg_color_tl } \tl_replace_all:Nnn \l__luatexcn_textbox_bg_rgb_tl { , } { ~ } % Convert font color to RGB \cs_if_exist:cTF { color @ \l__luatexcn_textbox_font_color_tl } { \exp_args:NV \extractcolorspec \l__luatexcn_textbox_font_color_tl \l_tmpa_tl \exp_args:NNx \convertcolorspec \l_tmpa_tl { rgb } \l_tmpb_tl \tl_set:Nx \l__luatexcn_textbox_font_rgb_tl { \l_tmpb_tl } } { \tl_set_eq:NN \l__luatexcn_textbox_font_rgb_tl \l__luatexcn_textbox_font_color_tl } \tl_replace_all:Nnn \l__luatexcn_textbox_font_rgb_tl { , } { ~ } % Convert border color to RGB \tl_set:No \l__luatexcn_textbox_border_color_tl { \l__luatexcn_textbox_border_color_tl } \cs_if_exist:cTF { color @ \l__luatexcn_textbox_border_color_tl } { \exp_args:NV \extractcolorspec \l__luatexcn_textbox_border_color_tl \l_tmpa_tl \exp_args:NNx \convertcolorspec \l_tmpa_tl { rgb } \l_tmpb_tl \tl_set:Nx \l__luatexcn_textbox_border_rgb_tl { \l_tmpb_tl } } { \tl_set_eq:NN \l__luatexcn_textbox_border_rgb_tl \l__luatexcn_textbox_border_color_tl } \tl_replace_all:Nnn \l__luatexcn_textbox_border_rgb_tl { , } { ~ } % Setup textbox params in _G.textbox (parsed once, used in Lua) \lua_now:e { vertical_textbox.setup({ column_aligns~=~[=[\luaescapestring{\tl_use:N~\l__luatexcn_textbox_col_align_tl}]=], floating~=~\bool_if:NTF~\l__luatexcn_textbox_floating_bool~{true}~{false}, floating_x~=~[=[\luaescapestring{\l__luatexcn_textbox_x_tl}]=], floating_y~=~[=[\luaescapestring{\l__luatexcn_textbox_y_tl}]=], floating_paper_width~=~[=[\luaescapestring{\l__luatexcn_textbox_floating_paper_width_tl}]=], outer_grid_height~=~\dim_to_decimal_in_sp:n { \l__luatexcn_content_grid_height_tl } }) } \lua_now:e {vertical_textbox.process_inner_box(\int_value:w~\l_tmpa_box,~{ n_cols~=~\int_use:N~\l__luatexcn_textbox_n_cols_int, outer_cols~=~\int_use:N~\l__luatexcn_textbox_outer_cols_int, height~=~[=[\luaescapestring{\tl_use:N \l__luatexcn_textbox_height_tl}]=], grid_width~=~\dim_to_decimal_in_sp:n { \l__luatexcn_textbox_inner_gw_dim }, grid_height~=~\dim_to_decimal_in_sp:n { \l__luatexcn_textbox_inner_gh_dim }, box_align~=~"\luaescapestring{\tl_use:N~\l__luatexcn_textbox_box_align_tl}", border~=~"\bool_if:NTF~\l__luatexcn_textbox_border_bool~{true}{false}", background_color~=~[=[\l__luatexcn_textbox_bg_rgb_tl]=], font_color~=~[=[\l__luatexcn_textbox_font_rgb_tl]=], font_size~=~[=[\luaescapestring{\l__luatexcn_textbox_font_size_tl}]=], border_shape~=~"\luaescapestring{\tl_use:N~\l__luatexcn_textbox_border_shape_tl}", border_color~=~[=[\l__luatexcn_textbox_border_rgb_tl]=], border_width~=~[=[\luaescapestring{\l__luatexcn_textbox_border_width_tl}]=], border_margin~=~[=[\luaescapestring{\l__luatexcn_textbox_border_margin_tl}]=], border_margin_x~=~[=[\luaescapestring{\l__luatexcn_textbox_border_margin_x_tl}]=], border_margin_y~=~[=[\luaescapestring{\l__luatexcn_textbox_border_margin_y_tl}]=], border_offset~=~[=[\luaescapestring{\l__luatexcn_textbox_border_offset_tl}]=], outer_margin~=~[=[\luaescapestring{\l__luatexcn_textbox_outer_margin_tl}]=], outer_border~=~\bool_if:NTF~\l__luatexcn_textbox_outer_border_bool~{true}{false}, outer_border_thickness~=~[=[\luaescapestring{\l__luatexcn_textbox_outer_border_thickness_tl}]=], outer_border_sep~=~[=[\luaescapestring{\l__luatexcn_textbox_outer_border_sep_tl}]=], padding_top~=~[=[\luaescapestring{\l__luatexcn_textbox_padding_top_tl}]=], padding_bottom~=~[=[\luaescapestring{\l__luatexcn_textbox_padding_bottom_tl}]=], transparent~=~\bool_if:NTF~\l__luatexcn_textbox_transparent_bool~{true}{false} }) } \setluatexattribute\cnverticaltextboxwidth{0} \setluatexattribute\cnverticaltextboxheight{0} \bool_if:NTF \l__luatexcn_textbox_floating_bool { \lua_now:e { vertical_textbox.register_floating_box(\int_value:w~\l_tmpa_box,~{ x~=~[=[\luaescapestring{\l__luatexcn_textbox_x_tl}]=], y~=~[=[\luaescapestring{\l__luatexcn_textbox_y_tl}]=] }) } } { \mode_leave_vertical: \box_use:N \l_tmpa_box } \group_end: } % 填充文本框 - Backwards compatible: accepts either integer (old syntax) or key-value options (new syntax) \NewDocumentCommand{\FillTextBox}{ O{} +m } {% \tl_set:Nn \l_tmpa_tl { #1 } \regex_match:nnTF { ^[0-9]+$ } { #1 } { \TextBox[height=#1, box-align=fill]{#2} } % Old syntax: just an integer height { \TextBox[#1, box-align=fill]{#2} } % New syntax: key-value options } % ============================================================ % Cell size resolution helpers (for border-shape commands) % Priority: content cell-width/cell-height param > font size (1em) % ============================================================ \cs_new:Nn \__luatexcn_textbox_resolve_cell_gw:N { % Inside textflow (jiazhu), use current font's 1em (small size) % instead of content cell_width (body text size) \int_compare:nNnTF { \the\cnverticaljiazhu } > { 0 } { \dim_set:Nn #1 { 1em } } { \tl_if_empty:NTF \l__luatexcn_content_cell_width_tl { \dim_set:Nn #1 { 1em } } { \dim_set:Nn #1 { \l__luatexcn_content_cell_width_tl } } } } % Resolve inner grid-height for border-shape textbox commands. % Use outer grid_height so the textbox's internal row pitch matches the % surrounding text — this prevents content overflow into the next row % (#96 follow-up: body \octagon{真珠} previously overlapped the next % glyph because gh = gw * 1.2 = 33.6pt > outer 28.5pt). Falls back to % 1.2em when no outer grid is set. \cs_new:Nn \__luatexcn_textbox_resolve_cell_gh:N { \int_compare:nNnTF { \the\cnverticaljiazhu } > { 0 } { \tl_if_empty:NTF \l__luatexcn_content_grid_height_tl { \dim_set:Nn #1 { 1.2em } } { \dim_set:Nn #1 { \l__luatexcn_content_grid_height_tl } } } { \tl_if_empty:NTF \l__luatexcn_content_cell_height_tl { \tl_if_empty:NTF \l__luatexcn_content_grid_height_tl { \dim_set:Nn #1 { 1.2em } } { \dim_set:Nn #1 { \l__luatexcn_content_grid_height_tl } } } { \dim_set:Nn #1 { \l__luatexcn_content_cell_height_tl } } } } % ============================================================ % Border shape shortcuts (using cell-based sizing) % % 修饰词组合命名体系: % 反白 = 黑底白字(无边框) % 墨围 = 矩形边框 % 八角墨围 = 八角形边框 % 反白 = 可叠加(墨围反白、八角墨围反白) % 带圈 = 圆形边框(独立) % ============================================================ % -- 反白:黑底白字,无边框 -- % 不强制 1.2x 高度(无边框,字格高度即可) \NewDocumentCommand{\反白}{ O{} m } { \__luatexcn_textbox_resolve_cell_gw:N \l_tmpa_dim \__luatexcn_textbox_resolve_cell_gh:N \l_tmpb_dim \TextBox[ background-color={0.2~0.2~0.2}, font-color=white, grid-width=\l_tmpa_dim, grid-height=\l_tmpb_dim, #1 ]{#2} } % -- 墨围:矩形黑色边框 -- \NewDocumentCommand{\墨围}{ O{} m } { \__luatexcn_textbox_resolve_cell_gw:N \l_tmpa_dim \__luatexcn_textbox_resolve_cell_gh:N \l_tmpb_dim \TextBox[ border-shape=rect, grid-width=\l_tmpa_dim, grid-height=\l_tmpb_dim, border-margin-x=0.05em, border-margin-y=0.1em, outer-margin=0.15em, #1 ]{#2} } % -- 墨围反白:矩形黑色边框 + 黑底白字 -- % border-offset 使黑色边框线画在背景之外(白色区域上可见) \NewDocumentCommand{\墨围反白}{ O{} m } { \__luatexcn_textbox_resolve_cell_gw:N \l_tmpa_dim \__luatexcn_textbox_resolve_cell_gh:N \l_tmpb_dim \TextBox[ background-color={0.2~0.2~0.2}, font-color=white, border-shape=rect, grid-width=\l_tmpa_dim, grid-height=\l_tmpb_dim, border-margin-x=0.05em, border-margin-y=0.1em, border-offset=0.1em, outer-margin=0.15em, #1 ]{#2} } % -- 八角墨围:八角形黑色边框 -- \NewDocumentCommand{\八角墨围}{ O{} m } { \__luatexcn_textbox_resolve_cell_gw:N \l_tmpa_dim \__luatexcn_textbox_resolve_cell_gh:N \l_tmpb_dim \TextBox[ border-shape=octagon, grid-width=\l_tmpa_dim, grid-height=\l_tmpb_dim, border-margin-x=0.05em, border-margin-y=0.1em, outer-margin=0.15em, #1 ]{#2} } % -- 八角墨围反白:八角形黑色边框 + 黑底白字 -- % border-offset 使黑色边框线画在背景之外(白色区域上可见) \NewDocumentCommand{\八角墨围反白}{ O{} m } { \__luatexcn_textbox_resolve_cell_gw:N \l_tmpa_dim \__luatexcn_textbox_resolve_cell_gh:N \l_tmpb_dim \TextBox[ background-color={0.2~0.2~0.2}, font-color=white, border-shape=octagon, grid-width=\l_tmpa_dim, grid-height=\l_tmpb_dim, border-margin-x=0.05em, border-margin-y=0.1em, border-offset=0.1em, outer-margin=0.15em, #1 ]{#2} } % -- 带圈:圆形边框 -- % 不强制 1.2x 高度(圆形几何已有视觉空间) \NewDocumentCommand{\带圈}{ O{} m } { \__luatexcn_textbox_resolve_cell_gw:N \l_tmpa_dim \__luatexcn_textbox_resolve_cell_gh:N \l_tmpb_dim \TextBox[ border-shape=circle, grid-width=\l_tmpa_dim, grid-height=\l_tmpb_dim, #1 ]{#2} } \ExplSyntaxOff% % ============================================================ % Aliases / 别名 % ============================================================ % Simplified Chinese / 简体 \NewCommandCopy{\文本框}{\TextBox} \NewCommandCopy{\文本框设置}{\textboxSetup} \NewCommandCopy{\填充文本框}{\FillTextBox} \NewDocumentCommand{\悬浮文本框}{ O{} +m }{\TextBox[floating=true, #1]{#2}} \NewDocumentCommand{\FloatingTextBox}{ O{} +m }{\TextBox[floating=true, #1]{#2}} % English \NewCommandCopy{\inverted}{\反白} \NewCommandCopy{\bordered}{\墨围} \NewCommandCopy{\borderedInverted}{\墨围反白} \NewCommandCopy{\octagon}{\八角墨围} \NewCommandCopy{\octagonBordered}{\八角墨围} \NewCommandCopy{\octagonBorderedInverted}{\八角墨围反白} \NewCommandCopy{\circled}{\带圈} % Traditional Chinese / 繁体 \NewCommandCopy{\文本框設置}{\textboxSetup} \NewCommandCopy{\帶圈}{\带圈} \NewCommandCopy{\墨圍}{\墨围} \NewCommandCopy{\墨圍反白}{\墨围反白} \NewCommandCopy{\八角墨圍}{\八角墨围} \NewCommandCopy{\八角墨圍反白}{\八角墨围反白} % ============================================================ % Chinese key aliases / 中文 Key 别名 % ============================================================ \ExplSyntaxOn \keys_define:nn { luatexcn / textbox } { % 简体 高度 .tl_set:N = \l__luatexcn_textbox_height_tl, 列数 .int_set:N = \l__luatexcn_textbox_n_cols_int, 外列数 .int_set:N = \l__luatexcn_textbox_outer_cols_int, 填充 .meta:n = { box-align = fill }, 框对齐 .tl_set:N = \l__luatexcn_textbox_box_align_tl, 边框 .bool_set:N = \l__luatexcn_textbox_border_bool, 版心 .bool_set:N = \l__luatexcn_textbox_banxin_bool, 列对齐 .meta:n = { column-align = #1 }, 纵对齐 .meta:n = { vertical-align = #1 }, 透明 .bool_set:N = \l__luatexcn_textbox_transparent_bool, 悬浮 .bool_set:N = \l__luatexcn_textbox_floating_bool, 悬浮纸宽 .tl_set:N = \l__luatexcn_textbox_floating_paper_width_tl, 横坐标 .tl_set:N = \l__luatexcn_textbox_x_tl, 纵坐标 .tl_set:N = \l__luatexcn_textbox_y_tl, 底色 .tl_set:N = \l__luatexcn_textbox_bg_color_tl, 字体颜色 .tl_set:N = \l__luatexcn_textbox_font_color_tl, 字号 .tl_set:N = \l__luatexcn_textbox_font_size_tl, 格宽 .meta:n = { grid-width = #1 }, 格高 .meta:n = { grid-height = #1 }, 边框形状 .tl_set:N = \l__luatexcn_textbox_border_shape_tl, 边框色 .tl_set:N = \l__luatexcn_textbox_border_color_tl, 边框宽 .tl_set:N = \l__luatexcn_textbox_border_width_tl, 边框间距 .tl_set:N = \l__luatexcn_textbox_border_margin_tl, 边框横距 .tl_set:N = \l__luatexcn_textbox_border_margin_x_tl, 边框纵距 .tl_set:N = \l__luatexcn_textbox_border_margin_y_tl, 外间距 .tl_set:N = \l__luatexcn_textbox_outer_margin_tl, 外边框 .bool_set:N = \l__luatexcn_textbox_outer_border_bool, 外边框粗细 .tl_set:N = \l__luatexcn_textbox_outer_border_thickness_tl, 外边框间距 .tl_set:N = \l__luatexcn_textbox_outer_border_sep_tl, % 繁体(与简体不同形的) 列數 .int_set:N = \l__luatexcn_textbox_n_cols_int, 外列數 .int_set:N = \l__luatexcn_textbox_outer_cols_int, 填充 .meta:n = { box-align = fill }, 框對齊 .tl_set:N = \l__luatexcn_textbox_box_align_tl, 邊框 .bool_set:N = \l__luatexcn_textbox_border_bool, 列對齊 .meta:n = { column-align = #1 }, 縱對齊 .meta:n = { vertical-align = #1 }, 透明 .bool_set:N = \l__luatexcn_textbox_transparent_bool, 懸浮 .bool_set:N = \l__luatexcn_textbox_floating_bool, 懸浮紙寬 .tl_set:N = \l__luatexcn_textbox_floating_paper_width_tl, 橫坐標 .tl_set:N = \l__luatexcn_textbox_x_tl, 縱坐標 .tl_set:N = \l__luatexcn_textbox_y_tl, 字號 .tl_set:N = \l__luatexcn_textbox_font_size_tl, 字體顏色 .tl_set:N = \l__luatexcn_textbox_font_color_tl, 格寬 .meta:n = { grid-width = #1 }, 格高 .meta:n = { grid-height = #1 }, 邊框形狀 .tl_set:N = \l__luatexcn_textbox_border_shape_tl, 邊框色 .tl_set:N = \l__luatexcn_textbox_border_color_tl, 邊框寬 .tl_set:N = \l__luatexcn_textbox_border_width_tl, 邊框間距 .tl_set:N = \l__luatexcn_textbox_border_margin_tl, 邊框橫距 .tl_set:N = \l__luatexcn_textbox_border_margin_x_tl, 邊框縱距 .tl_set:N = \l__luatexcn_textbox_border_margin_y_tl, 外間距 .tl_set:N = \l__luatexcn_textbox_outer_margin_tl, 外邊框 .bool_set:N = \l__luatexcn_textbox_outer_border_bool, 外邊框粗細 .tl_set:N = \l__luatexcn_textbox_outer_border_thickness_tl, 外邊框間距 .tl_set:N = \l__luatexcn_textbox_outer_border_sep_tl, } \ExplSyntaxOff \endinput%