CTeX-org / ctex-kit

Macro Packages and Scripts for Chinese TeX users
965 stars 124 forks source link

LuaLaTeX font fallback warning with luaotfload.add_fallback and luatexja #691

Open BenjaminGalliot opened 6 months ago

BenjaminGalliot commented 6 months ago

(Sorry to use English.)

I'm trying to use a virtual font combining several Unicode blocks, to have access to rarer characters very easily (without having to manually change the font).

The method I use in LuaLaTeX goes through luaotfload.add_fallback, but I get a warning (coming from luatexja).

I would like to know if this warning indicates a potential problem (particularly aesthetic, etc.), if it is possible to correct it, etc.

Here is the minimal working example (feel free to adapt your fonts!):

% !TEX program = lualatex

\documentclass{article}

\usepackage{ctex}

\directlua{
    luaotfload.add_fallback(
        "cjkfallback",
        {
            "TW-Kai-Ext-B-98_1:mode=harf;script=CJK;color=FF0000;",  % Red color to easily see fallbacks.
        }
    )
}

\setCJKfamilyfont{rm}[RawFeature={fallback=cjkfallback}]{TW-Kai-98_1}

\begin{document}

道𨕥

\end{document}

And the warning:

warning  (node filter): error: ...live/2023/texmf-dist/tex/luatex/luatexja/ltj-
jfmglue.lua:622: attempt to index a nil value (local 'm')

.
<argument> ...ype:D \tex_hskip:D \c_zero_dim \fi: \tex_par:D 
                                                  \hook_use:n {para/after}\@...

l.21 

Generally speaking, is there a better method with LuaLaTeX to create a virtual font combining several Unicode blocks?

muzimuzhi commented 6 months ago

Source code around line 622 in ltj-jfmglue.lua https://github.com/luatexja/luatexja/blob/f6f0b5136dff5b5fac80e9b81cb59b2e917a44d2/src/ltj-jfmglue.lua#L615-L631

do
   -- ...

   function set_np_xspc_jachar(Nx, x)
      local m = ltjf_font_metric_table[getfont(x)] -- <<< m is defined here
      local c, c_glyph = (not getcomponents(x) and ltjs_orig_char_table[x]), getchar(x)
      if c and c~=c_glyph then set_attr(x, attr_jchar_code, c) end
      c = c or c_glyph
      local cls = slow_find_char_class(c, m, c_glyph)
      Nx.met, Nx.class, Nx.char = m, cls, c;
      local mc = m.char_type; Nx.char_type = mc    -- <<< line 622
      if cls~=0 then set_attr(x, attr_jchar_class, cls) end
      Nx.pre  = table_current_stack[PRE + c]  or 0
      Nx.post = table_current_stack[POST + c] or 0
      Nx.xspc = table_current_stack[XSP  + c] or 3
      Nx.kcat = table_current_stack[KCAT + c] or 0
      Nx.auto_kspc, Nx.auto_xspc
       = not has_attr(x, attr_autospc, 0), not has_attr(x, attr_autoxspc, 0)
      return m, mc, cls
   end

   -- ...
end
wangweixuan commented 2 days ago

The solution is to use alternate fonts in LuaTeX-ja and CTeX:

\usepackage[fontset=none]{ctex}

\setCJKmainfont{TW-Kai-98_1}
\setCJKmainfont{TW-Kai-Ext-B-98_1}[Color=FF0000, CharRange={"20000->"2A6DD}]

% or

\setCJKmainfont{TW-Kai-98_1}[
  AlternateFont={
    {"20000->"2A6DD}{TW-Kai-Ext-B-98_1}{Color=FF0000}
  }
]

The problem with fallback fonts is that LuaTeX-ja requires that CJK fonts be defined using the \jfont macro in order to obtain their CJK-specific metric information. (Macros provided by CTeX, like \setCJKmainfont, expand to \jfont.)

However, luaotfload simply loads fallback fonts in lua, having nothing to do with jfont. Therefore the entry in ltjf_font_metric_table is missing and causes the error. That could result in some spacing problems.

A contrived workaround is to define the font with \jfont first, and use the predefined font as fallback:

\usepackage[fontset=none]{ctex}

\jfont\predefinedFallback={TW-Kai-Ext-B-98_1:color=FF0000;jfm=zh_CN/{quanjiao};-fallback} at 10.5bp
\directlua{
  luaotfload.add_fallback(
    "cjkfallback",
    {"TW-Kai-Ext-B-98_1:color=FF0000;jfm=zh_CN/{quanjiao}"}
  )
}
\setCJKmainfont[RawFeature={fallback=cjkfallback}]{TW-Kai-98_1}

The font features and the font size have to match exactly. The jfm feature is necessary for \jfont. The -fallback feature is appended by luaotfload.