The savebox dimensions are as accurate as they get. The issue is caused because you only use the height not the total height (= height + depth) of the box. Any box as a width, a height and a depth (the amount it goes below the baseline). You are setting the page size to its height only so cropping off an amount equal of the depth. Because you center the box then vertically and horizontally the cropping affects top and bottom.
You can fix this by adding either \dp\IBox
to \myheight
(which might require adjustments to the vertical centering, because it might be baseline specific) or simply ensure that there is no depth by using e.g. \raisebox
:
Second Case:
For your second case simply do:
\savebox\IBox{\raisebox{\depth}{\fbox{$\displaystyle E=mc^2$}}}
A more low level way to push the depth to the height would be:
\savebox\IBox{...}
\sbox\IBox{\raise\dp\IBox\box\IBox}
This has the benefit that you can use the lrbox
environment instead of \savebox
to allow verbatim or other special material which doesn't allow an macro wrapped around it.
First Case:
For your first case you still have to plan in the rule width and the separation (as \fbox
does), which should be added to \mywidth
and \myheight
. You should then center the box vertically and horizontally.
Alternatievly add the extra height and width manually:
\documentclass[cmyk]{minimal}
\usepackage{pstricks}
\newsavebox\IBox
\newlength\mymargin
\setlength\mymargin{2pt}
\savebox\IBox{%
\raisebox{\dimexpr\depth+\mymargin\relax}
[\dimexpr\totalheight+2\mymargin\relax]{\hspace\mymargin$\displaystyle E=mc^2$\hspace\mymargin}}
\newdimen\mywidth
\newdimen\myheight
\mywidth=\wd\IBox
\myheight=\ht\IBox
\paperwidth=\mywidth
\paperheight=\myheight
\voffset=-1in
\hoffset=-1in
\topskip=0bp
\special{papersize=\the\mywidth,\the\myheight}
\parindent=0cm
\pagecolor{cyan}
\begin{document}
\begin{pspicture}(\mywidth,\myheight)
\psframe[linecolor=red](\mywidth,\myheight)
\rput[lb](0,0){\usebox{\IBox}}
\end{pspicture}
\end{document}
A LuaTeX solution. Should work in all situations that I am aware of:
\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}
which yields:
(detail)
Bonus: it draws the base line if the depth of the glyph is not 0.
Here is a solution that replaces the glyphs by black rectangles (rules):
\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}
Best Answer
This approach is by no means automated, but can be made to manually work. It uses a
\boxxed
macro for putting things in boxes. However, manual intervention is still needed as follows:\mathop
and\mathrel
have to be manually introduced for a boxed operator or relation, since the box removes any memory of that.The
\ThisStyle{...\SavedStyle...}
syntax of thescalerel
package is used to preserve\scriptstyle
arguments in their proper style, once inside the box.The good news is that the kerning is preserved.