不使用 TeX 进行 TeX 中的字距调整和连字

不使用 TeX 进行 TeX 中的字距调整和连字

我试图获得与这个答案由 topskip 撰写(带有注释的扩展版本在TeX 没有 TeX 的文章)。我得到了一个包含 6 行带连字符的段落,但字距调整和连字符丢失了(关闭了?),因为它可以在字符周围看到在伏尔塔瓦河和信件中在办公室。

我使用 WinXP + TeX Live 2014 和 Lubuntu 13.10 + TeX Live 2013。我得到了相同的输出,字体是LinLibertine_R.otf

topskip 给出的第一个建议是跳过fontspec包的加载,因为包的处理方式可能与包不同。因此,我尝试直接加载和包,luaotfload而不是libertineluatextra(它们都加载包) ,但没有成功,没有错误,也没有警告。问题可能出在哪里?fontspecluacodeluaotfload

我们跑lualatex testfonts.tex

% lualatex testfonts.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
%\usepackage{luatextra}
%\usepackage{libertine}
\usepackage{luaotfload}
\usepackage{luacode}

\begin{document}
\font\main={file:LinLibertine_R.otf}
\main

\begin{luacode*}
function count_lines (head)
  local linecount = 0
  while head do
    if head.id == 0 then linecount = linecount + 1 end
    head = head.next
  end
  return linecount
end

function mknodes( text )
  local current_font = font.current()
  local font_parameters = font.getfont(current_font).parameters
  local n, head, last
  -- we should insert the paragraph indentation at the beginning
  head = node.new("glue")
  head.spec = node.new("glue_spec")
  head.spec.width = 20 * 2^16
  last = head

  for s in string.utfvalues( text ) do
    local char = unicode.utf8.char(s)
    if unicode.utf8.match(char,"%s") then
      -- its a space
      n = node.new("glue")
      n.spec = node.new("glue_spec")
      n.spec.width   = font_parameters.space
      n.spec.shrink  = font_parameters.space_shrink
      n.spec.stretch = font_parameters.space_stretch
    else -- a glyph
      n = node.new("glyph")
      n.font = current_font
      n.subtype = 1
      n.char = s
      n.lang = tex.language
      n.uchyph = 1
      n.left = tex.lefthyphenmin
      n.right = tex.righthyphenmin
    end

    last.next = n
    last = n
  end

  -- now add the final parts: a penalty and the parfillskip glue
  local penalty = node.new("penalty")
  penalty.penalty = 10000

  local parfillskip = node.new("glue")
  parfillskip.spec = node.new("glue_spec")
  parfillskip.spec.stretch = 2^16
  parfillskip.spec.stretch_order = 2

  last.next = penalty
  penalty.next = parfillskip

  -- just to create the prev pointers for tex.linebreak
  node.slide(head)
  return head
end

local txt = "VLTAVA office A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine."

tex.baselineskip = node.new("glue_spec")
tex.baselineskip.width = 14 * 2^16

local head = mknodes(txt)
lang.hyphenate(head)
head = node.kerning(head)
head = node.ligaturing(head)

local vbox
local size = 90
lines = 0
lines_goal = 6

while lines < lines_goal do
  texio.write_nl(string.format("Formatting text to %d mm",size))
  local copy_of_head = node.copy_list(head)
  vbox = tex.linebreak(copy_of_head,{ hsize = tex.sp(string.format("%dmm",size))})
  size = size - 10
  lines = count_lines(vbox)
  texio.write_nl(string.format("lines=%d",lines))
end

node.write(vbox)
\end{luacode*}

VLTAVA office
\end{document}

结果预览

答案1

对于 opentype 字体,luaotfload提供nodes.simple_font_handler处理所有字体操作(如连字和字距调整)以及 支持的所有其他功能的函数luaotfload。手册中没有宣传此功能,我在luaotfload源代码中找到了它。它在普通文本上被称为节点回调,但由于您直接从 Lua 创建节点,因此它不会对您的文本生效,您必须明确调用它:

local head = mknodes(txt)
lang.hyphenate(head)
head = nodes.simple_font_handler(head)

你不必再打电话node.ligaturing了,他们已经node.kerning打过电话了simple_font_handler

在此处输入图片描述

相关内容