Both Herbert and Alexander have offered solutions for dvips. Here, I'm taking inspiration from those answers plus the more convenient approach available in pdfTeX, plus a modified version of the pgf
method for XeTeX, and combining into a single approach. First, note that I'm assuming e-TeX and also using a somewhat 'LaTeX3-like' programming approach. I've also shared as much code as possible.
I'll use a single example but add comments along the way. First, as there are packages for the driver detections I'll load those.
\documentclass{article}
\usepackage{ifpdf,ifxetex}
\makeatletter
The main internal macro takes five arguments: the box to modify, then four dimension expressions to be clipped off the left, bottom, right and top respectively. You could also set up a similar approach to take a final size. The idea here is that the baseline is respected if possible, so there is a bit of care needed with the vertical placement so that the content only moves down while there is some depth available.
\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%
}
For each driver supported, there is an auxiliary. First, for dvips this is Herbert's method slightly altered (pgf
makes things very complex):
\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 }%
}%
}
As I said, pdfTeX makes life very easy :-)
\protected\long\def\box@clip@pdfmode#1%
{%
\pdfxform#1%
\setbox#1=\hbox{\pdfrefxform\pdflastxform}%
}
XeTeX is possibly the most complex one to tackle. The pgf
approach is used, but here I've removed a lot of unnecessary transformations. After reading the dvipdfmx manual, it becomes clear that the best approach is as follows
\protected\long\def\box@clip@xdvipdfmx#1%
{%
\setbox#1=\hbox
{%
The first special saves the current point and starts a new 'graphics level'. Using the bcontent
operation saves the current location automatically.
\special{pdf:bcontent }%
Draw a rectangle the size of the modified box: in pgf
this is done using the lower-level m
, l
and h
operations, but there is no gain in working that way. This will be located at 'current point' TeX-wise.
\special
{%
pdf:literal direct
0 -\to@bp{\dp#1} \to@bp{\wd#1} \to@bp{\ht#1 + \dp#1} re
}%
The W
operation specifies a clip, and n
finalises the path without any output (it's a 'no-op').
\special{pdf:literal direct W }%
\special{pdf:literal direct n }%
Insert the box and tidy up.
\box#1%
\special{pdf:econtent }%
}%
}
A simple conversion taken from Is there a command to convert cm to bp?
\long\def\to@bp#1{\strip@pt\dimexpr0.99626\dimexpr#1\relax\relax}
Wrap everything up in a user macro and finish the code block
\protected\long\def\boxclip#1#2#3#4#5{\box@clip#1{#2}{#3}{#4}{#5}}
\makeatother
\newbox\testbox
Now for some testing.
\begin{document}
\setbox\testbox=\hbox{Some test text with (g)}
\boxclip{\testbox}{10 pt}{2pt}{5pt}{2 pt}
\noindent\box\testbox{}
\end{document}
(I'll be adding this to LaTeX3 now I know how it works!) If you want to see the effect of various parts of the XeTeX code, comment out the W
line to turn off the clipping. You can also replace the n
operations by s
so that you get a box where the clipping path is.
In earlier versions of the answer, for XeTeX I used the content q
operation to save the current location, but this requires a series of manipulations to get the clip path and the box insert to line up. Using the bcontent
... econtent
pair is much clearer.
While using the XForm implementation for pdfTeX is convenient, in a case where code is to be shared between branches an alternative approach is possible. (The above could be viewed as an abuse of the XForm object system in any case).
\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
}%
}
The zero width box here is used to keep placement correct in the \pdfsave
/\pdfrestore
pair (which perform the same task as the bcontent
/econtent
pair for XeTeX but which should be places in the same output position.)
The pstool
package uses the error flag of the compilation/typesetting stage to determine if the typesetting has succeeded or not, so if you're seeing that red box there must be an error somewhere in the chain.
To help track down such problems, load pstool
with the following option:
\usepackage[mode=errorstop]{pstool}
and use -interaction=errorstopmode
in texniccentre; this will show up all output as it comes scrolling through, and will pause when an error occurs.
In the event that the figure typesetting succeeds, this would indicate there's a subsequent problem converting the DVI to PS and then to PDF (and then maybe cropping it). Try and run those steps manually on the pics/figure1.dvi
file (or whatever) that results in this case. Since you're using Windows, it's not impossible there's a ghostscript error or something along those lines in the way that pstool
is attempting to convert the file.
Best Answer
Update
After new requirement in comments, now theres just one environment
coolbox
with a mandatory argument (the file image to be used) and two optional ones:The code:
Using
tcolorbox
; adjust the settings according to your needs:The code:
If all the boxes are going to have this structure (i.e., an upper and a lower part), then (as cmhughes suggests in
his comment
) one can use\tcblower
andmiddle
to avoid manually producing the vertical separation: