在 Plain TeX/XeTeX 中缩放文本(\scalebox)使其变窄

在 Plain TeX/XeTeX 中缩放文本(\scalebox)使其变窄

我已经在网上查找了好几个小时了。基本上,我需要做这样的事情,我可以在 LaTeX 中使用这个graphicx包来完成:

\scalebox{.7}[1.0]{NARROW}

但!我需要使用清楚的\setboxTeX(准确地说是带有 PDF 的 XeTeX),最好不使用任何软件包。最简单、最直接的方法是什么?它与和有关吗 \wd?我只能尝试:

\def\narrow#1{
  \setbox0\hbox{#1}
  \multiply\wd0 by 0.7
  \box0
}

但这显然不起作用,它出错了 You can't use `\wd' after \multiply.

答案1

dgoodmaniii 的回答已经向您展示了您的代码为何不起作用,以及如何使其起作用。但是 TeX 本身不知道如何“缩放”事物。您只能更改框的尺寸,但框内的字符保持不变。要获得相同的缩放比例,\scalebox您需要特定于驱动程序的代码,而这些代码在不同的引擎之间会有所不同。

由于您使用 XeTeX,以下是\scalebox我从和中来的代码。 中的代码包含 warpper 宏,它使用和。 这两个宏放置了将执行缩放的 s (不是因为我的懒惰, 的第二个参数不再是可选的):graphics.stydvipdfmx.defgraphics.sty\scalebox\Gscale@start\Gscale@end\special\scalebox

在此处输入图片描述

\catcode`\@=11
\long\def\scalebox#1#2#3{%
  \leavevmode
  \def\Gscale@x{#1}\def\Gscale@y{#2}%
  \setbox\z@\hbox{{#3}}%
  \setbox\tw@\hbox{\Gscale@start\rlap{\copy\z@}\Gscale@end}%
  \ifdim#2\p@<\z@
    \ht\tw@-#2\dp\z@
    \dp\tw@-#2\ht\z@
  \else
    \ht\tw@#2\ht\z@
    \dp\tw@#2\dp\z@
  \fi
  \ifdim#1\p@<\z@
    \hbox to-#1\wd\z@{\kern-#1\wd\z@\box\tw@\hss}%
  \else
    \hbox to#1\wd\z@{\box\tw@\kern#1\wd\z@\hss}%
  \fi}
\def\GPT@space{ }
\def\Gscale@start{%
  \special{pdf:btrans}%
  \special{x:scale \Gscale@x\GPT@space\Gscale@y}}
\def\Gscale@end{\special{pdf:etrans}}
\catcode`\@=12

\scalebox{0.7}{1.0}{NARROW}\par
\scalebox{1.0}{1.0}{NARROW}\par
\scalebox{1.3}{1.0}{NARROW}\par

\bye

当然,仅加载graphicx.tex就容易得多(并且独立于引擎):

\input graphicx.tex

\scalebox{0.7}[1.0]{NARROW}\par
\scalebox{1.0}{NARROW}\par
\scalebox{1.3}[1.0]{NARROW}\par

\bye

答案2

它不起作用,因为它\wd基本上是一个运算符;你给它你想要的宽度的框。另外请记住,它\multiply不适用于浮点数,只适用于整数;所以如果你想乘以 0.7 之类的数字,你必须乘以 7,然后除以 10。

假设全长为\hsize,并且您想要一个 0.7 倍的盒子\hsize

\hbox to\hsize{This box will be the full width}
\newbox\mybox
\setbox\mybox\hbox to\hsize{\hfil}
\newdimen\mywidth\mywidth=\wd\mybox
\multiply\mywidth by7
\divide\mywidth by10
\hbox to\mywidth{This box will be the right width}
\bye

第一行纯粹是为了演示目的,显示行的全长。然后我们声明一个新的框,,并通过为其分配一个与该宽度相同的空值\mybox来确保其宽度也等于。然后我们声明一个新的,,并将其设置为等于的宽度。然后我们将其乘以 7 并除以 10,这相当于乘以 0.7。最后,我们在框中放入一些文本,如您所见,它的宽度为原始框的 70%。\hsize\hboxdimen\mywidth\mybox\mywidth\mywidth

当然,您可以将其包装在宏中:

\hbox to\hsize{This box will be the full width}

\newbox\mybox
\newdimen\mywidth
\def\width#1#2#3#4{%
    \setbox\mybox\hbox to#1{\hfil}
    \mywidth=\wd\mybox
    \multiply\mywidth by#2
    \divide\mywidth by#3
    \hbox to\mywidth{#4}
}%

\width{\hsize}{7}{10}{This box will be the short width}
\width{\hsize}{8}{10}{This box will be the short width}
\width{\hsize}{4}{10}{This box will be the short width}
\bye

这将产生以下内容:

在此处输入图片描述

如果需要文本换行,请将 换行到#4\hbox\vbox然后更改\hsize其中的 :

\newbox\mybox
\newdimen\mywidth
\def\width#1#2#3#4{%
    \setbox\mybox\hbox to#1{\hfil}
    \mywidth=\wd\mybox
    \multiply\mywidth by#2
    \divide\mywidth by#3
    \hbox to\mywidth{%
        \hfil%
        \vbox{%
            \hsize=\mywidth
            #4
        }%
        \hfil%
    }
}%

希望可以满足您的需要。

答案3

我尽可能简化了@phelype-oleinik 的例子,得出了以下结论:

\def\narrow#1{%
  % Enter horizonal mode to make sure we don't bork up the start of the
  % paragraph.
  \leavevmode%
  % Set the scale factors.
  \def\ScaleX{0.7}%
  \def\ScaleY{1.0}%
  % Set box zero to the box with the text as is, without scaling, to get
  % the width of this box.  Not sure if that can be done without \setbox.
  \setbox 0 \hbox{#1}%
  \def\NewWidth{\ScaleX \wd 0}%
  % The next box will overfull, but that's okay, as long as it's within
  % the new width.
  \hfuzz = \NewWidth%
  % Create a horizontal box with the new width containing the scaled
  % text.
  \hbox to \NewWidth {%
    \special{pdf:btrans}%
    % x:scale requires that the two numbers are separated by a space.
    \special{x:scale \ScaleX\space\ScaleY}%
    #1%
    \special{pdf:etrans}%
  }%
}

这对我来说很有效,但如果您发现任何潜在问题,请告诉我。

相关内容