解决方案和问题

解决方案和问题

我如何获取输入文本并将每个字符替换为代表该字符边界框的实心(和/或空心)矩形?如果两个字符因字距调整而更接近(例如microtype),则框会重叠。添加框不应改变文本的间距 - 我正在寻找字母的“草稿模式”。

解决方案和问题

Yiannis Lazarides 和 egreg 提出的两种解决方案似乎对单个单词的处理都还不错,尽管如上所述,字距调整似乎没有完全得到尊重。以下是结果(没有 markup/egreg/Yiannis):

在此处输入图片描述

但是,当涉及多个单词时,这两种解决方案都会失败。其中一个答案完全占用了一个空格,而另一个则过度补偿。它们似乎也都因换行符而卡住了。

在此处输入图片描述

答案1

LuaTeX 解决方案。应该适用于我所知的所有情况:

\documentclass{article}
\usepackage{luacode,luatexbase}
\begin{document}
\begin{luacode*}
local GLYPH_ID = node.id("glyph")

local number_sp_in_a_pdf_point = 65782

function math.round(num)
  return math.floor(num * 1000 + 0.5) / 1000
end

-- width/height/depth of a glyph and the whatsit node
local wd,ht,dp,w

-- head is a linked list (next/prev entries pointing to the next node)
function showcharbox(head)
  while head do
    if head.id == 0 or head.id == 1 then
      -- a hbox/vbox
      showcharbox(head.list)
    elseif head.id == GLYPH_ID then
      -- Create a pdf_literal node to draw a box with the dimensions
      -- of the glyph
      w = node.new("whatsit","pdf_literal")
      wd = math.round(head.width  / number_sp_in_a_pdf_point)
      ht = math.round(head.height / number_sp_in_a_pdf_point)
      dp = math.round(head.depth  / number_sp_in_a_pdf_point)

      -- draw a dashed line if depth not zero
      if dp ~= 0 then
        w.data = string.format("q 0.2 G 0.1 w 0 %g %g %g re S f [0.2] 0 d 0 0 m %g 0 l S Q",-dp,-wd,dp + ht,-wd)
      else
        w.data = string.format("q 0.2 G 0.1 w 0 %g %g %g re S f Q",-dp,-wd,dp + ht,-wd)
      end
      -- insert this new node after the current glyph and move pointer (head) to
      -- the new whatsit node
      w.next = head.next
      w.prev = head
      head.next = w
      head = w
    end
    head = head.next
  end
  return true
end

luatexbase.add_to_callback("post_linebreak_filter",showcharbox,"showcharbox")
\end{luacode*}

A \emph{wonderful} serenity has taken {\large possession} of my entire soul, like these
\textsl{sweet}
\textbf{mornings} of spring which I enjoy with my whole heart. I am alone, and feel the
charm of existence in this spot, \textbf{which} was created for the bliss of souls like
mine. I am so happy, my dear friend, so absorbed in the exquisite sense of
mere tranquil existence, that I neglect my talents. I should be incapable of
drawing a single stroke at the present moment; and yet I feel that I never was
a greater artist than now.

\end{document}

得出的结果是:

带框的文本

(细节)

带框的文本详细信息

奖励:如果字形的深度不为 0,它会绘制基线。


这是一个用黑色矩形(规则)替换字形的解决方案:

\documentclass{article}
\usepackage{luacode,luatexbase,microtype}
\begin{document}
\begin{luacode*}
local GLYPH_ID = node.id("glyph")

-- head is a linked list (next/prev entries pointing to the next node)
-- parent it the surrounding h/vbox
function showcharbox(head,parent)
  while head do
    if head.id == 0 or head.id == 1 then
      -- a hbox/vbox
      showcharbox(head.list,head)
    elseif head.id == GLYPH_ID then
      r = node.new("rule")
      r.width  = head.width
      r.height = head.height
      r.depth  = head.depth

      -- replace the glyph by
      -- the rule by changing the
      -- pointers of the next/prev
      -- entries of the rule node
      if not head.prev then
        -- first glyph in a list
        parent.list = r
      else
        head.prev.next = r
      end

      if head.next then
        head.next.prev = r
      end
      r.prev = head.prev
      r.next = head.next

      -- now the glyph points to
      -- nowhere and we should remove
      -- it from the memory
      node.free(head)

      head = r
    end
    head = head.next
  end
  return true
end

luatexbase.add_to_callback("post_linebreak_filter",showcharbox,"showcharbox")
\end{luacode*}

\hsize6cm

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. I am so happy, my dear friend, so absorbed in the exquisite sense of
mere tranquil existence, that I neglect my talents. I should be incapable of
drawing a single stroke at the present moment; and yet I feel that I never was
a greater artist than now.

\end{document}

字形被黑色规则替换

答案2

这是一个尊重字距调整(但不尊重连字符)的解决方案:

\documentclass{article}
\usepackage{xcolor}
\makeatletter
\def\showboxes#1{%
  \begingroup\fboxrule=.1pt \fboxsep=-\fboxrule
  \@showboxes#1\@showboxes\@empty
  \endgroup}
\def\@showboxes#1#2{%
  \ifx#2\@showboxes
    \fbox{\color{gray}#1}\expandafter\@gobble
  \else
    \setbox0=\hbox{#1\kern0pt#2}\setbox2=\hbox{#1#2}%
    \dimen0=\wd0 \advance\dimen0 -\wd2 % \dimen0 contains the kern between the two chars
    \fbox{\color{gray}#1}\kern-\dimen0
    \expandafter\@showboxes
  \fi#2}
\begin{document}
\showboxes{AVov}
\end{document}

在此处输入图片描述

要输入更多单词,只需添加

\usepackage{xparse}
\def\showboxesaux#1{\showboxes{#1} }
\NewDocumentCommand\Showboxes{>{\SplitList{ }}m}
  {\ProcessList{#1}\showboxesaux\unskip}

并使用

\Showboxes{The quick brown fox jumped over the lazy dog.}

但连字符不会被处理。

答案3

可能最好的是 TeXbook 中的代码,这个就留给你了。另一种选择是研究soul软件包中的代码并使用提供的扫描仪。

以下是改编版本:

\documentclass{article}
\usepackage{soul,graphicx,xcolor}
\fboxrule=0.1pt
\fboxsep=-\fboxrule
\begin{document}
\makeatletter
\def\SOUL@soeverytoken{%
  \fbox{\color{gray}\the\SOUL@token}}
\makeatother
\scalebox{7}{\color{purple}\so{ailbcdefgh}}
\end{document}

将灰色改为白色,使字母消失。

在此处输入图片描述

\fbox如果您需要补偿 0.1pt 规则或使用我已采纳的评论中 egreg 的建议,则需要将其更改为基本的 TeX 原语。

答案4

来自context当前的 TeXLive

\setuppagenumbering[location={}]
\definepapersize[DE][width=15cm,height=15cm]
\setuppapersize [DE][DE]
\setuplayout[width=13cm,height=13cm]
\definefontfeature[default][default][boundingbox={frame,blue,empty}]
\starttext
\bgroup
    \showglyphs
    \showfontkerns
    \showmakeup[hbox]
    \showmakeup[line]
%    \showallmakeup

    »Tee for Two« shows negative kerning.
    \input sapolsky \par
\egroup
\stoptext 

在此处输入图片描述

相关内容