LuaTeX 中控制标点应该更容易, luatex 中可以直接察看字符的bbox( 无须.spa 文件), 可以定义中文标点间的kerning, ...。
只是它现在的编译速度实在是个问题。
LuaTeX / pdftex 中有\lpcode 与 \rpcode, 应该更容易实现标点边界对齐。
问题是, 在我的测试中, \lpcode只对英文有效, 奇怪。
下面的代码可以压缩相邻标点,但行首/行末不能对齐。- % -*- coding: utf-8 -*-
- %\documentclass{article}
- \pdfoutput 1
- \pdfprotrudechars=1
- \directlua{
- callback.register('define_font',
- function(name, size)
- filename=kpse.find_file(name,"truetype fonts")
- if (filename) then
- ttffont = fontloader.to_table(fontloader.open(filename))
- if ttffont then
- f = { }
- f.name = ttffont.fontname
- f.fullname = ttffont.names[1].names.fullname
- f.size = size
- f.characters = {}
- names_of_char = { }
- for char, glyph in pairs(ttffont.map.map)
- do
- names_of_char[ttffont.glyphs[glyph].name]
- = ttffont.map.backmap[glyph]
- end
- for char, glyph in pairs(ttffont.map.map) do
- glyph_table = ttffont.glyphs[glyph]
- f.characters[char] = {
- index = glyph,
- width = glyph_table.width * size/256,
- name = glyph_table.name,
- }
- f.characters[char].xl =glyph_table.boundingbox[1]
- f.characters[char].xr =glyph_table.boundingbox[3]
- end
- local puncts = {
- 0x2018,0x201C,0x300C,0x300E,0x3014,0xFF08,0xFF3B,0xFF5B,0x3008,0x300A,0x3016,0x3010, %pre
- 0x2500,0x2014,0x2026,0x3001,0x3002,0xFF0C,0xFF0E,0xFF1A,0xFF1B,0xFF01,0xFF1F,0xFF05, %post
- 0x3015,0xFF09,0xFF3D,0xFF5D,0x3009,0x300B,0x3017,0x3011,0x2019, 0x201D,0x300D,0x300F %post
- }
- local kerns = { }
- halfwidth = ttffont.units_per_em/2
- for keya, chara in pairs(puncts) do
- if f.characters[chara] then
- % margin kerning
- if keya < 13 then
- lpcode = f.characters[chara].xl*4-112
- if lpcode>0 then
- f.characters[chara].left_protruding =lpcode
- end
- else
- rpcode = (228 - f.characters[chara].xr) *4
- if rpcode>0 then
- f.characters[chara].right_protruding = rpcode
- end
- end
- % kerning between punctuation
- kerns = { }
- kernoff = ttffont.units_per_em *9/10 - f.characters[chara].xr
- if kernoff > halfwidth then
- kernoff = halfwidth
- end
- for keyb, charb in pairs(puncts) do
- if f.characters[charb] then
- kerns[names_of_char[f.characters[charb].name]] = - kernoff * size/256
- end
- end
- f.characters[chara].kerns = kerns
- end
- end
- f.characters[96].left_protruding = -500
- f.characters[22909].left_protruding = -500
- f.filename = filename
- f.type = 'real'
- f.format = 'truetype'
- f.cidinfo = {
- registry = "Adobe",
- ordering = "Identity",
- supplement = 0,
- version = 1
- }
- end
- else
- f = font.read_tfm(name, size)
- f.characters[96].left_protruding = 500
- end
- return f
- end)
- }
- \font\myfont "SimSun" at 11pt
- \parindent 0pt
- \myfont
- lpcode of “ = \directlua{f=font.getfont(font.current())
- tex.print(f.characters[\number`“].left_protruding)}
- lpcode of 好 = \directlua{f=font.getfont(font.current())
- tex.print(f.characters[\number`好].left_protruding)}
- “行首标点”不能对齐。标点挤压则没问题。例如,“相邻两个标点占$0.5+1.0 em$宽度”。
- 好像lpcode 对true type 不起作用。
- \font\aa "cmr10" at 10pt\aa
- `This example' shows that lpcode works for English.
- lpcode works for English.
- lpcode works for English.
- lpcode works for English.
- lpcode works for English.
- lpcode works for English.
- \bye
复制代码 |