% 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-decorate.sty % Character decoration support for vertical typesetting % This is a subpackage of luatex_cn % \RequirePackage{expl3} \RequirePackage{xparse} \ProvidesExplPackage {decorate/luatex-cn-decorate} {2026/02/18} {0.3.0} {Character Decoration Support} % Decorate Command - Apply decoration to each character in content % Syntax: \decorate[char=。, color=red, xshift=0pt, yshift=0pt]{content} % Each character in {content} will have the decoration character applied \tl_new:N \l__luatexcn_decorate_char_tl \tl_new:N \l__luatexcn_decorate_color_tl \tl_new:N \l__luatexcn_decorate_xshift_tl \tl_new:N \l__luatexcn_decorate_yshift_tl \tl_new:N \l__luatexcn_decorate_font_size_tl \tl_new:N \l__luatexcn_decorate_scale_tl \keys_define:nn { luatexcn / decorate } { char .tl_set:N = \l__luatexcn_decorate_char_tl, char .initial:n = 。, color .tl_set:N = \l__luatexcn_decorate_color_tl, color .initial:n = red, xshift .tl_set:N = \l__luatexcn_decorate_xshift_tl, xshift .initial:n = 0pt, yshift .tl_set:N = \l__luatexcn_decorate_yshift_tl, yshift .initial:n = 0pt, font-size .tl_set:N = \l__luatexcn_decorate_font_size_tl, font-size .initial:n = , scale .tl_set:N = \l__luatexcn_decorate_scale_tl, scale .initial:n = 1.0, } % Internal command to add decoration marker after current character \cs_new:Npn \__luatexcn_decorate_one:n #1 { #1 \lua_now:e { local~constants~=~require('core.luatex-cn-constants') constants.register_decorate( "\luaescapestring{\l__luatexcn_decorate_char_tl}", "\luaescapestring{\l__luatexcn_decorate_xshift_tl}", "\luaescapestring{\l__luatexcn_decorate_yshift_tl}", "\luaescapestring{\l__luatexcn_decorate_font_size_tl}", "\luaescapestring{\l__luatexcn_decorate_color_tl}", font.current(), "\luaescapestring{\l__luatexcn_decorate_scale_tl}" ) } \box0\scan_stop: } \NewDocumentCommand{\decorate}{ O{} m }{% \group_begin: \keys_set:nn { luatexcn / decorate } { #1 } \tl_map_function:nN { #2 } \__luatexcn_decorate_one:n \group_end: } % ============================================================================ % CJK Key Aliases (中文键值别名) % ============================================================================ % --- decorate namespace --- \keys_define:nn { luatexcn / decorate } { 字符 .tl_set:N = \l__luatexcn_decorate_char_tl, 颜色 .tl_set:N = \l__luatexcn_decorate_color_tl, 顏色 .tl_set:N = \l__luatexcn_decorate_color_tl, 横偏 .tl_set:N = \l__luatexcn_decorate_xshift_tl, 橫偏 .tl_set:N = \l__luatexcn_decorate_xshift_tl, 横移 .tl_set:N = \l__luatexcn_decorate_xshift_tl, 橫移 .tl_set:N = \l__luatexcn_decorate_xshift_tl, 纵偏 .tl_set:N = \l__luatexcn_decorate_yshift_tl, 縱偏 .tl_set:N = \l__luatexcn_decorate_yshift_tl, 纵移 .tl_set:N = \l__luatexcn_decorate_yshift_tl, 縱移 .tl_set:N = \l__luatexcn_decorate_yshift_tl, 字号 .tl_set:N = \l__luatexcn_decorate_font_size_tl, 字號 .tl_set:N = \l__luatexcn_decorate_font_size_tl, 缩放 .tl_set:N = \l__luatexcn_decorate_scale_tl, 縮放 .tl_set:N = \l__luatexcn_decorate_scale_tl, } % ============================================================================ % EmphasisMark (着重号/圈点) - Convenience command for emphasis marking % Applies a circle mark (。) to the right side of each character % Syntax: \EmphasisMark[color=red]{content} % ============================================================================ \tl_new:N \l__luatexcn_emphasis_color_tl \keys_define:nn { luatexcn / emphasis } { color .tl_set:N = \l__luatexcn_emphasis_color_tl, color .initial:n = red, } % --- emphasis namespace CJK aliases --- \keys_define:nn { luatexcn / emphasis } { 颜色 .tl_set:N = \l__luatexcn_emphasis_color_tl, 顏色 .tl_set:N = \l__luatexcn_emphasis_color_tl, } % ============================================================================ % CJK Aliases (中文别名) % ============================================================================ % Simplified Chinese / 简体 \NewCommandCopy{\装饰}{\decorate} \NewDocumentCommand{\EmphasisMark}{ O{} m }{% \group_begin: \keys_set:nn { luatexcn / emphasis } { #1 } \decorate[char=。, scale = 1.5, xshift=-0.7em, color=\l__luatexcn_emphasis_color_tl]{#2} \group_end: } \NewCommandCopy{\着重号}{\EmphasisMark} % ============================================================================ % 改 (Fix/Correction) Command - Mark a character as corrected % Used in classical Chinese text editing: 甲\改{乙} means "甲 is corrected to 乙" % This overlays a 、(deletion mark) on the previous character and places the % replacement character at bottom-right corner at half the font size % Syntax: \改{replacement character} \NewDocumentCommand{\fix}{ m }{% \group_begin: % First: overlay a 、 symbol to mark deletion (centered on the character) \lua_now:e { local~constants~=~require('core.luatex-cn-constants') constants.register_decorate( "、", "0em", "0em", nil, "black", nil, 2 ) }% \box0\scan_stop: % Second: add the replacement character at bottom-right, half size \lua_now:e { local~constants~=~require('core.luatex-cn-constants') constants.register_decorate( "\luaescapestring{#1}", "-0.6em", "0.5em", nil, "black", nil, 0.6 ) }% \box0\scan_stop: \group_end: } \NewCommandCopy{\改}{\fix} % Traditional Chinese / 繁体 \NewCommandCopy{\裝飾}{\decorate} \NewCommandCopy{\著重號}{\EmphasisMark} % ============================================================================ % Underline / WavyUnderline - Now provided by luatex-cn-linemark.sty % The old glyph-based implementation has been replaced with PDF line drawing. % Commands \Underline, \WavyUnderline, \下划线, \波浪线 etc. are defined there. % ============================================================================ \ExplSyntaxOff% % \endinput%