# -*- mode: Perl -*-
# /=====================================================================\ #
# | framed | #
# | Implementation for LaTeXML | #
# |=====================================================================| #
# | Part of LaTeXML: | #
# | Public domain software, produced as part of work done by the | #
# | United States Government & not subject to copyright in the US. | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov> #_# | #
# | http://dlmf.nist.gov/LaTeXML/ (o o) | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Package::Pool;
use strict;
use warnings;
use LaTeXML::Package;
#======================================================================
# {framed} Normal framed block-level box,
# Actually, is potentially higher than block-level; It can contain structure-level markup!
DefEnvironment('{framed}', sub {
my ($document, %props) = @_;
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
insertBlock($document, $props{body},
framed => 'rectangle',
framecolor => $props{framecolor},
cssstyle => 'padding:' . $props{margin} . 'pt;border-width:' . $props{border} . 'pt'); },
properties => sub { (framecolor => Black,
margin => LookupRegister('\FrameSep')->ptValue,
border => LookupRegister('\FrameRule')->ptValue); });
# {oframed} "open" framed box, the top/bottom is open when it splits across pages.
# That shouldn't matter for us (?)
DefEnvironment('{oframed}', sub {
my ($document, %props) = @_;
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
insertBlock($document, $props{body},
framed => 'rectangle',
framecolor => $props{framecolor},
cssstyle => 'padding:' . $props{margin} . 'pt;border-width:' . $props{border} . 'pt'); },
properties => sub { (framecolor => Black,
margin => LookupRegister('\FrameSep')->ptValue,
border => LookupRegister('\FrameRule')->ptValue); });
# {shaded} a shaded box; uses "shadecolor" for background color; otherwise, no frame.
# Note that the shading "bleeds" into the margin (whatever that means)
# The next four are identical.
# No frame, but with a background color;
# put that color explicitly on the outer block so it applies to full width!
DefEnvironment('{shaded}', sub {
my ($document, %props) = @_;
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
insertBlock($document, $props{body},
backgroundcolor => $props{backgroundcolor},
cssstyle => 'padding:' . $props{margin} . 'pt'); },
beforeDigest => sub {
MergeFont(background => LookupValue('color_shadecolor')); },
properties => sub { (backgroundcolor => LookupValue('font')->getBackground,
margin => LookupRegister('\FrameSep')->ptValue); });
# {shaded*} Same as {shaded}, but the shading ends at the margin.
# For us, that's pretty much identical.
DefEnvironment('{shaded*}', sub {
my ($document, %props) = @_;
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
insertBlock($document, $props{body},
backgroundcolor => $props{backgroundcolor},
cssstyle => 'padding:' . $props{margin} . 'pt'); },
beforeDigest => sub {
MergeFont(background => LookupValue('color_shadecolor')); },
properties => sub { (backgroundcolor => LookupValue('font')->getBackground,
margin => LookupRegister('\FrameSep')->ptValue); });
# {snugshade} Same as {shaded}, but with a tight fit around the contents.
# doesn't use \FrameSep?
DefEnvironment('{snugshade}', sub {
my ($document, %props) = @_;
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
insertBlock($document, $props{body},
backgroundcolor => $props{backgroundcolor},
cssstyle => 'padding:' . $props{margin} . 'pt'); },
beforeDigest => sub {
MergeFont(background => LookupValue('color_shadecolor')); },
properties => sub { (backgroundcolor => LookupValue('font')->getBackground,
margin => LookupRegister('\fboxsep')->ptValue); }); # Not \FrameSep
DefEnvironment('{snugshade*}', sub {
my ($document, %props) = @_;
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
insertBlock($document, $props{body},
backgroundcolor => $props{backgroundcolor},
cssstyle => 'padding:' . $props{margin} . 'pt'); },
beforeDigest => sub {
MergeFont(background => LookupValue('color_shadecolor')); },
properties => sub { (backgroundcolor => LookupValue('font')->getBackground,
margin => LookupRegister('\fboxsep')->ptValue); });
DefEnvironment('{leftbar}', sub {
my ($document, %props) = @_;
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
insertBlock($document, $props{body}, framed => 'left', framecolor => $props{framecolor},
cssstyle => 'border-width:3pt;padding-left:10pt'); },
properties => sub { (framecolor => Black); });
# Expects: TFFrameColor to color the frame
# Kinda clumsy to deal with a fake title...
# Should this be some kind of generic float? (but it doesn't float)
DefEnvironment('{titled-frame} Undigested', sub {
my ($document, $title, %props) = @_;
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
insertBlock($document, $props{body},
framed => 'rectangle', framecolor => $props{framecolor},
backgroundcolor => $props{backgroundcolor},
cssstyle => 'padding:8pt;border-width:2pt'); },
afterDigestBegin => sub {
Digest(Invocation(T_CS('\@titledframe@title'), $_[1]->getArg(1))); },
properties => sub { (framecolor => LookupValue('color_TFFrameColor'),
backgroundcolor => LookupValue('font')->getBackground); });
DefMacro('\@titledframe@title{}',
'\@@titledframe@title{{\fboxsep8pt\fboxrule2pt\pagecolor{TFFrameColor}\textcolor{TFTitleColor} {#1}}}');
DefConstructor('\@@titledframe@title{}', "<ltx:text cssstyle='display:block;margin:-8pt -8pt 8pt -8pt;padding:8pt'>#1</ltx:text>");
#======================================================================
# Customization:
# --- Is there any way to leverage anything that someone might do with \FrameCommand?
# \FrameCommand : The above approach makes \FrameCommand (default \fbox) kinda hard to use???
# \FirstFrameCommand, \LastFrameCommand, \MidFrameCommand :
# These can be defined by the user and used when displaying a box that gets broken over pages.
DefMacro('\FrameCommand',
'\setlength\fboxrule{\FrameRule}\setlength\fboxsep{\FrameSep}\fbox');
DefMacro('\FirstFrameCommand', '\FrameCommand');
DefMacro('\MidFrameCommand', '\FrameCommand');
DefMacro('\LastFrameCommand', '\FrameCommand');
# \FrameRule (used for \fboxrule)
# \FrameSep (used for \fboxsep)
DefRegister('\FrameRule' => LookupRegister('\fboxrule'));
DefRegister('\FrameSep' => Dimension(LookupRegister('\fboxsep')->valueOf * 3));
#======================================================================
# \makeFramed, \endMakeFramed; {MakeFramed}
# \FrameRestore, \FrameHeightAdjust,
DefRegister('\OuterFrameSep' => Dimension(0)); # should be \maxdimen
#
#======================================================================
1;