如何防止单词在 ConTeXt 中超出边缘?

如何防止单词在 ConTeXt 中超出边缘?

我有一份包含 25 个字符宽的列的文档。我已将语言设置为美国英语,并且出现了一些连字符,但是,我发现在很多地方,科学术语没有连字符。列显示如下:

This is a column with     This is another colu-
some  text.  It looks     umn of text.  Notice
fine most of the time,    how some of the text
but sometimes superscientficom the left column
words   do  not  fit.     also  appears  here?
  • 文档源是由脚本生成的,因此我无法轻易地手动将所有这些单词连字符连接起来。

  • 我已经尝试了所有可用的设置tolerance\setuptolerance[horizontal,stretch]这是唯一可以阻止这些单词跑出页面的设置,但它也会在所有其他单词之间产生很大的空格,这并不理想。

例如:

This is a column with     This is another colu-
some  text.  It looks     umn of text.  Notice
fine most of the time,    how some of the text
but         sometimes     from    the     left
superscientific words     column also  appears
do       not      fit.    here?

我怎样才能防止这些词语跑到下一列,同时又不导致文档中出现其他严重问题?

答案1

有几个选择或许可以改善你的情况。

增加单词间距

一种方法是告诉 ConTeXt 优先考虑更大的单词间距,以便单词可以悄悄进入相邻列。但正如你所说,仅此一项就可能导致不可接受的大间隙。

\setupcolumns [tolerance={verytolerant,stretch}]

协助 TeX 进行连字符连接

正如您所说,这对您来说不是一个选择,因为单词是自动生成的,但总的来说,这会导致不常见单词的良好连字。

\hyphenation{su-per-scien-ti-fic}

启用字体扩展

仅此一点可能对窄列没有太大帮助,但与其他方法结合可能会改善整体效果,因为 TeX 可以稍微改变各个字符的宽度,从而实现更好的换行。

\definefontfeature [default] [default] [expansion=quality]
\setupalign [hz]

使用更宽的列

这可能是改善这种情况最简单的方法。但是,布局通常是固定的,无法改变。

使用右对齐

在对齐不齐的文本中,很难判断单个单词是否超出了页边距。但使用较宽的列时也是如此。人们并不总是有更改布局的自由。

如您所见,这并非易事,尤其是对于自动生成的文本。窄栏总是很棘手。当您查看栏目较窄的杂志时,您经常会注意到单词间距特别宽(或更糟:单词间距特点间距,这是最糟糕的选择)。

答案2

总体来说:不要使用列,\hsize排版段落时避免使用不合理的短 es。Marco 已经给了你一些答案,可能会让你在排版上好的结果。

如果这仍然不能满足你的需求,而且你不能简单地用较短的单词重写文本,那么你不妨考虑转向暗面™:你可以诉诸字母间距就像报纸和其他垃圾印刷品一样。以下代码——我改编自辉煌的chickenize 包(请参阅其手册以获取文档)——允许您为不同的值定义环境。

将此代码片段保存为lsp_adj.lua

thirddata         = thirddata or { }
thirddata.lsp_adj = { }
local lsp_adj     = thirddata.lsp_adj
lsp_adj.callbacks = { }

local nodecopy                     = node.copy
local nodeid                       = node.id
local nodeinsert_before            = node.insert_before
local nodenew                      = node.new
local nodetraverse_id              = node.traverse_id
local nodesinstallattributehandler = nodes.installattributehandler
local nodestasksappendaction       = nodes.tasks.appendaction
local nodestasksdisableaction      = nodes.tasks.disableaction

--- For tests later.
local GLYPH_NODE = nodeid"glyph"
local DISC_NODE  = nodeid"disc"

lsp_adj.new_callback = function (id, stretch)
  --- Prepare a glue; this will be copied all over.
  local letterspace_glue   = nodenew(nodeid"glue")
  local letterspace_spec   = nodenew(nodeid"glue_spec")
  letterspace_spec.width   = tex.sp"0pt"
  letterspace_spec.stretch = tex.sp(stretch)
  letterspace_glue.spec    = letterspace_spec

  --- We’re gonna need a nobreak style penalty too. Else there will be
  --- line breaks inside words.
  local letterspace_pen    = nodenew(nodeid"penalty")
  letterspace_pen.penalty  = 10000

  --- Generate a callback; note the order of arguments.
  local cbk = function (_, _, head)
    for glyph in nodetraverse_id(GLYPH_NODE, head) do
      --- Insert glue between glyphs and ligatures.
      local prev = glyph.prev
      if prev and prev.id == GLYPH_NODE or prev.id == DISC_NODE then
        local g = nodecopy(letterspace_glue)
        nodeinsert_before(head, glyph, g)
        --- Don’t allow breaks here.
        nodeinsert_before(head, g, nodecopy(letterspace_pen))
      end
    end
    return head
  end

  --- Registering a callback requires some verbosity in Context.
  --- But it’s well worth it ...
  local cbk_id = "lsp_" .. id
  lsp_adj.callbacks[id] = nodesinstallattributehandler{
    name        = cbk_id,
    namespace   = thirddata.lsp_adj,
    processor   = cbk,
  }
  nodestasksappendaction(
    "processors",
    -- This one is for users according to node-tsk.lua.
    "before",
    "thirddata.lsp_adj.callbacks." .. id
  )
  nodestasksdisableaction(
    "processors",
    "thirddata.lsp_adj.callbacks." .. id
  )
end

并使用以下代码进行测试:

\ctxloadluafile{lsp_adj.lua}{}
\dontcomplain

\setuplayout[middle]
\setuplayout[backspace=1cm,topspace=1cm]

\unprotect

%%% Firstly, set some grotesquely unesthetic default.
\newdimen\letter_space_stretch \letter_space_stretch=2pt

\def\defineletterspace{\dodoubleempty\do_define_letter_space}

\def\do_define_letter_space[#1][#2]{%
  \begingroup
  \edef\id{#1}%
  \ifsecondargument
    \ctxlua{
      thirddata.lsp_adj.new_callback(\!!bs\id\!!es, \!!bs#2\!!es)
    }%
    \expandafter\gdef\csname start\id\endcsname{%
      \ctxlua{
        nodes.tasks.enableaction(
          \!!bs processors\!!es,
          \!!bs thirddata.lsp_adj.callbacks.#1\!!es
        )
      }%
    }%
    \expandafter\gdef\csname  stop\id\endcsname{%
      \ctxlua{
        nodes.tasks.disableaction(
          \!!bs processors\!!es,
          \!!bs thirddata.lsp_adj.callbacks.#1\!!es
        ) 
      }%  
    }%  
  \fi 
  \endgroup%
}   

\protect

%%% Now we can define our environments for testing.  Note that this is
%%% no module so you won’t get corresponding setups.
\defineletterspace [smalllsp]  [.5pt]
\defineletterspace [mediumlsp] [1pt]
\defineletterspace [biglsp]    [2pt]
\starttext

%%% For reference: typeset the demo text without letterspacing.
\startcolumns[n=4]
  \input knuth
\stopcolumns

\hairline

\startsmalllsp
  \startcolumns[n=4]
    \input knuth
  \stopcolumns
\stopsmalllsp

\hairline

\startbiglsp
  \startcolumns[n=4]
    \input knuth
  \stopcolumns
\stopbiglsp

\hairline

\startmediumlsp
  \startcolumns[n=4]
    \input knuth
  \stopcolumns
\stopmediumlsp

\stoptext

结果在审美上不会令人满意,但根据字母间距因素,它可能会满足您的限制。

达斯维达排版

相关内容