返回列表 回复 发帖

[LuaTeX] 中文支持方案讨论

anyway,这个不是主要问题。我个人觉得直接去掉CTeX包中调用西文字体的部分。这个不是CTeX该干的活。用户需要让他们自己载去。

另外LuaTeX的支持你觉得应该怎么做?
是我们直接用Hans 的ConTeXt的字体脚本(该脚本已经可以在plain TeX中使用,中文标点和断行处理都正确),还是自己写个LuaCJK?

(不过不管怎么写,都会没法用。LuaTeX编译一次载个字体能让我烧一壶早茶)

[ 本帖最后由 LiYanrui 于 2009-5-12 08:13 编辑 ]

回复 #29 yulewang 的帖子

> 直接用Hans 的ConTeXt的字体脚本(该脚本已经可以在plain TeX中使用,中文标点和断行处理都正确),还是自己写个LuaCJK?

Hans 的那个,有没有中文标点和断行的例子?
技术潜水员
原帖由 yulewang 于 2009-5-7 19:23 发表
anyway,这个不是主要问题。我个人觉得直接去掉CTeX包中调用西文字体的部分。这个不是CTeX该干的活。用户需要让他们自己载去。

另外LuaTeX的支持你觉得应该怎么做?
是我们直接用Hans 的ConTeXt的字体脚本 ...
第一个,已经去掉了。

第二个,ConTeXt 的我不清楚,LaTeX 的最好有一层类似 xeCJK 这样的包,可以试试在 xeCJK 基础上扩展,如果太麻烦,那就另写一个,在 ctex 宏包里可以新增一个 ctex-luatex-engine 用来处理这个。

回复 #31 jjgod 的帖子

ConTeXt这里的情况是这样的。ConTeXt中包含了一系列字体载入脚本,支持任意的LuaTeX支持的字体。同时也包含了一个中文的脚本,能够自动地切换字体、压缩标点、断行等。后来,Hans把前者从ConTeXt分离开来并为一个文件,写成了一个叫做luatex-fonts-merged.lua的脚本,这个脚本可以在plain TeX中使用。而后者其实只有两个文件(scrp-ini.lua, scrp-cjk.lua),虽然Hans在和我的邮件中表示不愿意merge到前者的脚本中,但其实我们自己可以方便地用在plain TeX中。也就是说,目前LuaTeX使用ConTeXt中提供的那些脚本(字体载入脚本+中文脚本),已经可以在plain TeX中使用中文。


我不知道CJK或者xeCJK需要提供哪些API,知道了我们才能模拟一个…… (是不是ctex-cjk-common.sty中出现的那些\CJKxxx呢?)

有个问题要问一下:xeCJK的断行机制为何不是采用xetex line break locale的呢?好像是自己实现的?

不过我大致看了,xeCJK对于XeTeX的依赖,仅仅在于 interchar token 机制的几个命令,和 encoding 相关的命令(LuaTeX不支持其他encoding,因此暂时不考虑),这些命令包括了:

\XeTeXinterchartokenstate
\XeTeXcharclass
\XeTeXinterchartoks

有条捷径就是直接采用Lua中的 node/token 的库,来实现这三个命令。然后 xeCJK 理论上就能够直接被port到LuaTeX上,虽然这种port并不符合LuaTeX的风格。

因此事实上是这几条路:

- 采用ConTeXt中分离给plain TeX的字体载入脚本和中文脚本,不提供CJK层,仅仅写个载入中文字体的中间层,然后直接把CTeX给port到这层很薄的中间层上。
- 不使用中文脚本,仅用字体载入脚本,我们手动地实现一个LuaCJK,模拟CJK干的事情,然后再把CTeX折腾到LuaCJK上。
- 不使用中文脚本,仅使用字体载入脚本,手动实现一个XeTeX那三条命令的克隆(LuaInterCharToken),然后把xeCJK给port到LuaInterCharToken上,再把CTeX给port到xeCJK上……

回复 #32 yulewang 的帖子

ConTeXt 分离出来的脚本在标点压缩、中英文间距处理方面表现的不好,现在还需要很脏的 hack 才可以达到较好的效果(得根据具体的字体去 hack),现在只能用它的字体载入脚本了。

回复 #33 LiYanrui 的帖子

XeTeX也需要特定的字体用特定的数字去hack的。那个spa就是干这个事情的。

其实LuaTeX可以做到字体无关,因为luatex会计算字体的 bounding box。我在邮件列表上说过多次,没人理我。

回复 #34 yulewang 的帖子

你说的第二条路,再配合你说的字体 bounding box 计算,倒是可以试试。

反正现在是解决 LaTeX 的问题,跟 Hans 他们也没关系。另外,这个问题解决了,可以为 ConTeXt 单独弄一个中文处理模块,也可以不再用 Hans 那套中文方案了。

回复 #35 LiYanrui 的帖子

问题就在于我写不出CJK来。CJK代码我压根没看懂过……

写个interchartok估计还有指望。

ConTeXt那脚本你改改会有指望不?

回复 #36 yulewang 的帖子

要是理清头绪,也许可以改好 ConTeXt 的脚本。我现在不知道怎么在 luatex 里调用你说的那几个分离出来的脚本来写含有中文的 Plain TeX 文档。所以,前面我还问你有没有例子。

CJK 我就更不熟悉了,我现在还不清楚 xeCJK 跟 CJK 有没有关系。如果把底下的机制通过 luatex api 做出来,再模拟 CJK 的宏,应该不困难吧。
LuaTeX 中控制标点应该更容易, luatex 中可以直接察看字符的bbox( 无须.spa 文件), 可以定义中文标点间的kerning, ...。
只是它现在的编译速度实在是个问题。

LuaTeX / pdftex 中有\lpcode 与 \rpcode, 应该更容易实现标点边界对齐。
问题是, 在我的测试中, \lpcode只对英文有效, 奇怪。

下面的代码可以压缩相邻标点,但行首/行末不能对齐。
  1. % -*- coding: utf-8 -*-
  2. %\documentclass{article}

  3. \pdfoutput 1
  4. \pdfprotrudechars=1

  5. \directlua{
  6. callback.register('define_font',
  7.   function(name, size)
  8.     filename=kpse.find_file(name,"truetype fonts")
  9.     if (filename) then
  10.       ttffont = fontloader.to_table(fontloader.open(filename))
  11.       if ttffont then
  12.         f = { }
  13.         f.name = ttffont.fontname
  14.         f.fullname = ttffont.names[1].names.fullname
  15.         f.size = size
  16.         f.characters = {}

  17.         names_of_char = { }
  18.         for char, glyph in pairs(ttffont.map.map)
  19.         do
  20.           names_of_char[ttffont.glyphs[glyph].name]
  21.             = ttffont.map.backmap[glyph]
  22.         end

  23.         for char, glyph in pairs(ttffont.map.map) do
  24.           glyph_table = ttffont.glyphs[glyph]

  25.           f.characters[char] = {
  26.             index = glyph,
  27.             width = glyph_table.width * size/256,
  28.             name = glyph_table.name,
  29.           }
  30.           f.characters[char].xl =glyph_table.boundingbox[1]
  31.           f.characters[char].xr =glyph_table.boundingbox[3]
  32.         end

  33.         local puncts = {
  34.           0x2018,0x201C,0x300C,0x300E,0x3014,0xFF08,0xFF3B,0xFF5B,0x3008,0x300A,0x3016,0x3010, %pre
  35.           0x2500,0x2014,0x2026,0x3001,0x3002,0xFF0C,0xFF0E,0xFF1A,0xFF1B,0xFF01,0xFF1F,0xFF05, %post
  36.           0x3015,0xFF09,0xFF3D,0xFF5D,0x3009,0x300B,0x3017,0x3011,0x2019, 0x201D,0x300D,0x300F %post
  37.           }

  38.         local kerns = { }
  39.         halfwidth = ttffont.units_per_em/2

  40.         for keya, chara in pairs(puncts) do
  41.           if f.characters[chara] then
  42.             % margin kerning
  43.             if keya < 13 then
  44.               lpcode = f.characters[chara].xl*4-112
  45.               if lpcode>0 then
  46.                 f.characters[chara].left_protruding =lpcode
  47.               end
  48.             else
  49.               rpcode = (228 - f.characters[chara].xr) *4
  50.               if rpcode>0 then
  51.                 f.characters[chara].right_protruding = rpcode
  52.               end
  53.             end
  54.             % kerning between punctuation
  55.             kerns = { }
  56.             kernoff = ttffont.units_per_em *9/10 - f.characters[chara].xr
  57.             if kernoff > halfwidth then
  58.               kernoff = halfwidth
  59.             end

  60.             for keyb, charb in pairs(puncts) do
  61.               if f.characters[charb] then
  62.                 kerns[names_of_char[f.characters[charb].name]] = - kernoff * size/256
  63.               end
  64.             end
  65.             f.characters[chara].kerns = kerns
  66.           end
  67.         end
  68.         f.characters[96].left_protruding = -500
  69.         f.characters[22909].left_protruding = -500


  70.         f.filename = filename
  71.         f.type = 'real'
  72.         f.format = 'truetype'
  73.         f.cidinfo = {
  74.           registry = "Adobe",
  75.           ordering = "Identity",
  76.           supplement = 0,
  77.           version = 1
  78.         }
  79.       end
  80.     else
  81.       f = font.read_tfm(name, size)
  82.       f.characters[96].left_protruding = 500
  83.     end
  84.   return f
  85.   end)
  86. }





  87. \font\myfont "SimSun" at 11pt

  88. \parindent 0pt

  89. \myfont



  90. lpcode of “ = \directlua{f=font.getfont(font.current())
  91.    tex.print(f.characters[\number`“].left_protruding)}

  92. lpcode of 好 = \directlua{f=font.getfont(font.current())
  93.    tex.print(f.characters[\number`好].left_protruding)}




  94. “行首标点”不能对齐。标点挤压则没问题。例如,“相邻两个标点占$0.5+1.0 em$宽度”。

  95. 好像lpcode 对true type 不起作用。



  96. \font\aa "cmr10" at 10pt\aa

  97. `This example' shows that lpcode works for English.

  98. lpcode works for English.
  99. lpcode works for English.
  100. lpcode works for English.
  101. lpcode works for English.
  102. lpcode works for English.


  103. \bye
复制代码
返回列表