我喜欢剪辑任意 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 中更方便的方法,以及pgf
XeTeX 方法的修改版本,并结合成一种方法。首先,请注意,我假设使用 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
这是使用较低级别的m
、l
和h
操作完成的,但这样做没有任何好处。这将位于 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
相同的任务,但应放置在相同的输出位置。)bcontent
econtent
答案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 坐标存储到llx
、lly
、urx
、ury
Postscript 变量中。这些变量稍后可用于定义剪辑矩形。
编辑:
下面是一个\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