Another approach, usable with LuaLaTeX. The following sample document was made with the files below.

The TeX input file
\documentclass{article}
\directlua{ require("drawboxes")}
\usepackage{graphicx,atbegshi}
\AtBeginShipout {\directlua{drawboxes.visual_debug()}}
\begin{document}
\hsize 3in
A wonderful serenity has taken possession of my entire soul, like these sweet
mornings of spring which I enjoy with my whole heart.
$$ e=mc^2 $$
\includegraphics[width=4cm]{cow} % from context distribution
\end{document}
and the Lua file (drawboxes.lua
):
module(...,package.seeall)
local factor = 65782 -- PDF points vs. TeX points
-- This returns the node which has the glue settings
-- Old LuaTeX versions have a sub node called "spec"
-- new LuaTeX has width, stretch etc. within the glue node.
local function getgluespec(anode)
if node.has_field(anode,"spec") then
return anode.spec
else
return anode
end
end
-- The argument must be a box (hbox or vbox)
local function draw_elements(box)
local glue = node.id('glue')
local hlist = node.id('hlist')
local vlist = node.id('vlist')
local parent = box
local head = box.list
-- We are only interested in the contents of the box (box.list). But we
-- keep the reference to the box (parent), so we know if we are in horizontal
-- or vertical mode.
-- head is a pointer to a node, which is a fundamental data structure in TeX
-- for example: a node with id 1 denotes a \vbox with height, depth, and
-- everything we know from TeX. A node with id 10 is a "glue" with the
-- plus and minus and "1fill" values in a sub node (glue_spec)
-- The contents of a box is a node list, connected by pointers in the attribute
-- "next" that point to the next element in the list or nil, if there is no next
-- element (= the last item in the box).
while head do
if head.id == hlist or head.id == vlist then
-- we are in an hbox or in a vbox. Since we want to debug the contents
-- of the box, we need to recursively call this function with the
-- contents of the box. We supply the parent (= the current box), so
-- we know if we are in vertical or horizontal mode and we know about the
-- caluclated glue ratio (and sign)
draw_elements(head)
-- now that the contents of the current box is handled, we only need to draw
-- a box around the contents of the box, which is stored in head.list. So we
-- create a "pdf literal" node and insert it at the head of the list
-- (and -- we must not forget that -- change the pointer to the contents
-- of the list to the new "pdf literal", otherwise it exists but is not
-- part of the box and therefore not inserted into the pdf).
-- The dimensions of the box are stored in the attributes width, height and depth.
local wd = head.width / factor
local ht = (head.height + head.depth) / factor
local dp = head.depth / factor
local pdfliteral = node.new("whatsit","pdf_literal")
if head.id == hlist then -- hbox
-- Wow, this looks complicated. It isn't. This instruction is a PDF instruction
-- to draw a box (<ll_x> <ll_y> <ur_x> <ur_y> re s) with a 50% grey (0.5 g) and
-- a rule width of 0.1 (0.1 w). This is enclosed in q .. Q so that the color
-- change does not affect the next graphics operation in the PDF file.
pdfliteral.data = string.format("q 0.5 G 0.1 w 0 %g %g %g re s Q", -dp, wd, ht)
else
-- a vbox is downwards, so the height must be negative
pdfliteral.data = string.format("q 0.1 G 0.1 w 0 %g %g %g re s Q", 0, wd, -ht)
end
-- node.insert_before( head_of_list, current_node, node_to_insert)
-- inserts the new node (pdfliteral) before the the first entry of the box
-- and returns the new head of the list (which is identical to the pdf literal)
head.list = node.insert_before(head.list,head.list,pdfliteral)
elseif head.id == glue then
local spec = getgluespec(head)
local wd = spec.width -- the natural width of the glue
local color = "0.5 G"
-- The entries such as "plus 1fil" only take effect when the maximum glue order
-- of the parent box has the same number of "l"s. If there is a glue with
-- "0pt plus 1fil" and another one with "0pt plus 1 fill", the former has no effect.
-- The glue_sign gives the "direction" (shrink/stretch) and the stretch_order and
-- shrink_order give the maximum number of "l" of the fill commands. Only apply
-- if they match. We also change the color of the markers to differantiate between
-- no stretch/shrink (gray), stretch (blue) and shrink (magenta).
if parent.glue_sign == 1 and parent.glue_order == spec.stretch_order then
wd = wd + parent.glue_set * spec.stretch
color = "0 0 1 RG"
elseif parent.glue_sign == 2 and parent.glue_order == spec.shrink_order then
wd = wd - parent.glue_set * spec.shrink
color = "1 0 1 RG"
end
pdfliteral = node.new("whatsit","pdf_literal")
-- The parent.id tells us if the glue is horizontal or vertical
if parent.id == hlist then
-- The horizontal glue is drawn with a dash pattern of [0.2] 0 for small dots
pdfliteral.data = string.format("q %s [0.2] 0 d 0.5 w 0 0 m %g 0 l s Q",color,wd / factor)
else -- vlist
-- The vertical glue is drawn with tiny marks at the beginning and the end
-- and also a small dash pattern. Therefore the PDF string is rahter long.
pdfliteral.data = string.format("q 0.1 G 0.1 w -0.5 0 m 0.5 0 l -0.5 %g m 0.5 %g l s [0.2] 0 d 0.5 w 0.25 0 m 0.25 %g l s Q",-wd / factor,-wd / factor,-wd / factor)
end
node.insert_before(parent.list,head,pdfliteral)
else
-- Any other node (for example a glyph node - a character). Probably not interesting.
end
-- next node in our list. If the list is at the end, head becomes nil and
-- the loop ends.
head = head.next
end
end
-- The box "AtBeginShipoutBox" holds the page contents.
function visual_debug()
draw_elements(tex.box["AtBeginShipoutBox"])
end
You can use a minipage with the width as a proportion of textwidth
.
\documentclass{article}
\usepackage{lipsum}
\begin{document}
\fbox{\begin{minipage}{0.9\textwidth}
\lipsum[1]
\end{minipage}}
\end{document}
The \begin{minipage}...\end{minipage}
puts a block of text in its own block. The 0.9\textwidth
provides the sizing parameter.
To enclose everything in a frame you can use \fbox
.
Best Answer
You can use
\boxed
command fromamsmath
packageTo add colors and labels below boxes