如何使用低级 PS 命令剪辑 TeX 框?

如何使用低级 PS 命令剪辑 TeX 框?

我喜欢剪辑任意 TeX 框 ( \hbox),但不使用较大的图形相关包,如 PGF/TikZ 或 PSTricks。这旨在用于不应强制用户也加载其中一个包的包中。

clip这里我的意思与选项(与viewport或 一起trim)的作用相同\includegraphics:一些外部材料不再显示。我只想将其应用于 TeX 框。我意识到这取决于输出驱动程序。我已经找到了一个pdftex使用 PDF 命令的解决方案。 我现在正在寻找 DVI/PS 解决方案,即一些\special剪辑 Tex 框的说明。非常欢迎有关其他司机的任何提示。

我的两个包gincltex和都需要这个adjustbox,它们都将 的功能扩展\includegraphics到任意 TeX 框。我目前所做的只是使用 PGF 来实现这一点:我将内容放在一个节点中并相应地剪辑图片。因为内容是装箱的,所以我可以预先计算所需的大小。

所以基本上我正在寻找宏的低级定义,例如:

\@clipbox{<llx>}{<lly>}{<urx>}{<ury>}{<boxnumber>}

它接受先前保存的框并从该框中剪下四个金额(ll= 左下方,ur= 右上角)。


为了pdftex$TEXMF/tex/latex/pdftex-def/pdftex.def我在(的驱动文件)中找到了相关代码graphics,它告诉我首先使用常规 TeX 命令修剪框(即,修剪到\lower左下角\hskip边距,并根据右上角限制框高度( \ht)和宽度( ) 。图像的深度设置为零,但我必须以不同的方式处理。)。之后,它使用以下低级宏来实际剪切框:\wd\dp

\pdfxform<boxnumber>
\pdfrefxform\pdflastxform

我想象对于 DVI 模式(dvps驱动程序),我需要一个 PostScript\special命令来执行相同操作。这样的命令是什么样子的?有什么解决方案吗dvipdf

答案1

Herbert 和 Alexander 都为 dvips 提供了解决方案。在这里,我从这些答案中汲取灵感,加上 pdfTeX 中更方便的方法,以及pgfXeTeX 方法的修改版本,并结合成一种方法。首先,请注意,我假设使用 e-TeX,并且还使用了一种有点“类似 LaTeX3”的编程方法。我还分享了尽可能多的代码。

我将使用单个示例,但会添加注释。首先,因为有驱动程序检测包,所以我将加载它们。

\documentclass{article}
\usepackage{ifpdf,ifxetex}
\makeatletter

主要内部宏需要五个参数:要修改的框,然后是要分别从左侧、底部、右侧和顶部裁剪的四个维度表达式。您也可以设置类似的方法来获取最终尺寸。这里的想法是尽可能尊重基线,因此在垂直放置时需要多加注意,以便内容仅在有一定深度时向下移动。

\protected\long\def\box@clip#1#2#3#4#5%
  {%
    \ht#1\dimexpr\ht#1 - \dimexpr#5\relax\relax
    \ifdim\dp#1>\dimexpr#3\relax
      \dp#1\dimexpr\dp#1 - \dimexpr#3\relax\relax
    \else
      \setbox#1=\hbox
        {\lower\dimexpr\dimexpr#3\relax - \dp#1\relax\box#1}%
      \dp#1\z@
    \fi
    \wd#1\dimexpr\wd#1-\dimexpr#4\relax\relax
    \setbox#1=\hbox
      {%
        \hskip-\dimexpr#2\relax
        \box#1%
      }%
    \ifxetex
      \expandafter\box@clip@xdvipdfmx
    \else
      \ifpdf
        \expandafter\expandafter\expandafter\box@clip@pdfmode
      \else
        \expandafter\expandafter\expandafter\box@clip@dvips
      \fi
    \fi
    #1%
  }

对于每个支持的驱动程序,都有一个辅助程序。首先,对于 dvips,这是 Herbert 的方法,略有改动(pgf使事情非常复杂的):

\protected\long\def\box@clip@dvips#1%
  {%
    \setbox#1=\hbox
      {%
        \special
          {%
            ps:
              /mtrxc matrix currentmatrix def 
              currentpoint gsave
              translate
              Resolution 72 div VResolution 72 div scale
              0 -\to@bp{\dp#1} neg  \to@bp{\wd#1} \to@bp{\ht#1 + \dp#1} neg
              rectclip
              mtrxc setmatrix 
          }%
        \box#1%
        \special{ps: grestore }%
      }%
  }

正如我所说,pdfTeX 让生活变得非常轻松 :-)

\protected\long\def\box@clip@pdfmode#1%
  {%
    \pdfxform#1%
    \setbox#1=\hbox{\pdfrefxform\pdflastxform}%
  }

XeTeX 可能是最复杂的。虽然pgf使用了这种方法,但在这里我删除了很多不必要的转换。阅读 dvipdfmx 手册后,很明显最好的方法如下

\protected\long\def\box@clip@xdvipdfmx#1%
  {%
    \setbox#1=\hbox
      {%

第一个特殊操作保存当前点并开始新的“图形级别”。使用该bcontent操作会自动保存当前位置。

        \special{pdf:bcontent }%

绘制一个与修改后的框大小相同的矩形:pgf这是使用较低级别的mlh操作完成的,但这样做没有任何好处。这将位于 TeX 中的“当前点”。

          \special
            {%
              pdf:literal direct 
                0 -\to@bp{\dp#1} \to@bp{\wd#1} \to@bp{\ht#1 + \dp#1} re 
            }%

W操作指定一个剪辑,并n确定路径而不进行任何输出(它是“无操作”)。

          \special{pdf:literal direct W }%
          \special{pdf:literal direct n }%

插入盒子并整理好。

                \box#1%
              \special{pdf:econtent }%
      }%
  }

简单转换自有没有将 cm 转换为 bp 的命令?

\long\def\to@bp#1{\strip@pt\dimexpr0.99626\dimexpr#1\relax\relax}

将所有内容包装在用户宏中并完成代码块

\protected\long\def\boxclip#1#2#3#4#5{\box@clip#1{#2}{#3}{#4}{#5}}
\makeatother

\newbox\testbox

现在进行一些测试。

\begin{document}
\setbox\testbox=\hbox{Some test text with (g)}
\boxclip{\testbox}{10 pt}{2pt}{5pt}{2 pt}

\noindent\box\testbox{}

\end{document}

(现在我知道它是如何工作的了,我会把它添加到 LaTeX3 中!)如果您想查看 XeTeX 代码各个部分的效果,请注释掉该W行以关闭剪切。您也可以用 替换n操作,s这样您就可以得到一个包含剪切路径的框。


在早期版本的答案中,对于 XeTeX,我使用操作content q来保存当前位置,但这需要一系列操作才能使剪辑路径和框插入对齐。使用bcontent...econtent对更清晰。


虽然使用 pdfTeX 的 XForm 实现很方便,但在分支之间共享代码的情况下,也可以采用其他方法。(无论如何,上述方法都可以被视为对 XForm 对象系统的滥用)。

\protected\long\def\box@clip@pdfmode#1%
  {%
    \setbox#1=\hbox
      {%
        \pdfsave
          \pdfliteral direct
            {%
              0 -\to@bp{\dp#1} \to@bp{\wd#1} \to@bp{\ht#1 + \dp#1} re W n
            }%
          \hbox to 0pt{\copy#1\hss}%
        \pdfrestore
        \hskip \wd#1
      }%
  }

这里的零宽度框用于保持\pdfsave/对中的正确位置(其执行与 XeTeX 的/对\pdfrestore相同的任务,但应放置在相同的输出位置。)bcontentecontent

答案2

%%%% 仅用于部分演示,稍后删除这两行

\documentclass{article} 
\usepackage[T1]{fontenc}
\usepackage{kpfonts}
\makeatletter
\def\clipbox#1#2#3#4#5{% 
\leavevmode%   
  \special{ps: 
   /mtrxc matrix currentmatrix def 
   currentpoint  
   gsave translate 
   0 0 10 0 360 arc 0 0 1 gsave fill grestore setrgbcolor 0.5 setlinewidth  %%%%%%
   #1 #2 neg moveto #3 0 rlineto 0 #4 neg rlineto #3 neg 0 rlineto closepath  stroke %%%%
   newpath 
   #1 #2 neg #3 #4 neg 
   rectclip newpath  
   mtrxc setmatrix 
   }%
   #5% 
  \special{ps: grestore }%
}

\begin{document} 

\fontsize{60}{62} \selectfont Foo
\clipbox{30}{30}{400}{200}{Foo}
Foo

\end{document}

在此处输入图片描述

这是一个具有尺寸和正确缩放比例的解决方案:

\documentclass{article} 
\makeatletter
\newlength\@templlx
\newlength\@templly
\newlength\@tempurx
\newlength\@tempury
\def\clipbox#1#2#3#4#5{% 
  \@templlx=#1%
  \@templly=#2%
  \@tempurx=#3%
  \@tempury=#4%
\leavevmode%   
  \special{ps: 
   /mtrxc matrix currentmatrix def 
   currentpoint  
   gsave translate Resolution 72 div VResolution 72 div scale
   newpath 
   \strip@pt\@templlx\space \strip@pt\@templly\space neg 
   \strip@pt\@tempurx\space \strip@pt\@tempury\space neg 
   rectclip newpath  
   mtrxc setmatrix 
   }%
   #5% 
  \special{ps: grestore }%
}
\makeatother
\begin{document} 
\rule{1cm}{1cm}
\clipbox{0cm}{0cm}{1cm}{1cm}{\rule{4cm}{4cm}}%
\rule{1cm}{1cm}

\end{document}

第二个正方形未剪裁,尺寸为 4cm x 4cm

在此处输入图片描述

答案3

地方

\special{ps: currentpoint /lly exch def /llx exch def}

\special{ps: currentpoint /ury exch def /urx exch def}

在框的所需左下角和右上角。这会将 Postscript 坐标存储到llxllyurxuryPostscript 变量中。这些变量稍后可用于定义剪辑矩形。

编辑:

下面是一个\trimbox命令示例,它与您的请求类似,\@clipbox需要 4 个 TeX 长度和一个框号。但是,四个 TeX 长度指定了要剪切的框边缘的测量量。

请注意,字形比其框略大。请参阅 的第一次使用\trimbox

q被放入盒子中,以表明非零深度的盒子得到正确处理。

\def\trimbox#1#2#3#4#5{%
  \leavevmode%
  \special{ps: gsave}%
  \hbox to 0pt{\hskip#1\special{ps: currentpoint pop /llx exch def}\hss}%
  \hbox to 0pt{\hskip\wd#5\hskip-#3\special{ps: currentpoint pop /urx exch def}\hss}%
  \raise-\dp#5\hbox{\raise#2\hbox{\special{ps: currentpoint /lly exch def pop}}}%
  \raise\ht#5\hbox{\raise-#4\hbox{\special{ps: currentpoint /ury exch def pop}}}%
  \special{ps: llx lly urx llx sub ury lly sub rectclip}%
  \copy#5%
  \special{ps: grestore}%
}

\setbox0=\hbox{Foo q Bar}

x\trimbox{0pt}{0pt}{0pt}{0pt}{0}x\par
x\trimbox{2pt}{2pt}{2pt}{2pt}{0}x

\bye

相关内容