# -*- mode: Perl -*-
# /=====================================================================\ #
# | diagbox | #
# | 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;
#======================================================================
DefKeyVal('diagbox', 'dir', '');
DefKeyVal('diagbox', 'width', 'Dimension');
DefKeyVal('diagbox', 'height', 'Dimension');
DefKeyVal('diagbox', 'innerwidth', 'Dimension');
DefKeyVal('diagbox', 'innerleftsep', 'Dimension'); # ignored
DefKeyVal('diagbox', 'innerrightsep', 'Dimension'); # ignored
DefKeyVal('diagbox', 'outerleftsep', 'Dimension'); # ignored
DefKeyVal('diagbox', 'outerrightsep', 'Dimension'); # ignored
DefKeyVal('diagbox', 'leftsep', 'Dimension'); # ignored
DefKeyVal('diagbox', 'rightsep', 'Dimension'); # ignored
DefKeyVal('diagbox', 'trim', ''); # ignored
DefKeyVal('diagbox', 'font', '');
DefKeyVal('diagbox', 'linewidth', '');
DefKeyVal('diagbox', 'linecolor', '');
# NOTE that this macro SNIFFS out an optional 3rd argument!!!
# Possibly should turn off guess headers in containing alignment?
DefMacro('\diagbox OptionalKeyVals:diagbox {}{}', sub {
my ($gullet, $kv, $A, $B) = @_;
my $M;
if ($gullet->ifNext(T_BEGIN)) {
$M = $B; $B = $gullet->readArg; }
my $dir = $kv && ToString($kv->getValue('dir')) || 'NW';
if ($dir) {
}
my $font = $kv && $kv->getValue('font');
return Invocation(T_CS('\lx@diagbox'),
$kv,
Invocation(T_CS('\lx@diagbox@head'), T_LETTER('l'), $font, $A),
$M && Invocation(T_CS('\lx@diagbox@head'), T_LETTER(($dir =~ /W/ ? 'l' : 'r')), $font, $M),
Invocation(T_CS('\lx@diagbox@head'), T_LETTER('r'), $font, $B)); });
DefMacro('\lx@diagbox@head{}{}{}', '{#2\shortstack[#1]{#3}}');
DefConstructor('\lx@diagbox RequiredKeyVals:diagbox {}[]{}',
"<ltx:picture width='&pxValue(#width)' height='&pxValue(#height)'>"
. "?#line1(<ltx:line points='#line1' stroke='#linecolor' stroke-width='#linewidth'/>)()"
. "?#line2(<ltx:line points='#line2' stroke='#linecolor' stroke-width='#linewidth'/>)()"
. "<ltx:g transform='translate(#Ax,#Ay)'"
. " innerwidth='#Aw' innerheight='#Ah' innerdepth='#Ad' class='ltx_svg_fog'>"
. "<ltx:inline-block>#A</ltx:inline-block>"
. "</ltx:g>"
. "<ltx:g transform='translate(#Bx,#By)'"
. " innerwidth='#Bw' innerheight='#Bh' innerdepth='#Bd' class='ltx_svg_fog'>"
. "<ltx:inline-block>#B</ltx:inline-block>"
. "</ltx:g>"
. "?#M(<ltx:g transform='translate(#Mx,#My)'"
. " innerwidth='#Mw' innerheight='#Mh' innerdepth='#Md' class='ltx_svg_fog'>"
. "<ltx:inline-block>#M</ltx:inline-block>"
. "</ltx:g>)()"
. "</ltx:picture>",
afterConstruct => sub { $_[0]->addClass($_[0]->getNode, 'ltx_nopad'); },
reversion => '\diagbox[#1]{#2}{#4}{#3}', # Wrong!
afterDigest => sub {
my ($stomach, $whatsit) = @_;
# Annoying: All svg units, and computations, are in pixels!
my ($kv, $A, $M, $B) = $whatsit->getArgs;
my $dir = $kv && ToString($kv->getValue('dir')) || 'NW';
my ($Aw, $Ah, $Ad) = map { roundto($_->pxValue) } $A->getSize; $Ah += $Ad;
my ($Bw, $Bh, $Bd) = map { roundto($_->pxValue) } $B->getSize; $Bh += $Bd;
my ($Mw, $Mh, $Md) = $M && map { roundto($_->pxValue) } $M->getSize; $Mh += $Md if $Mh;
my $maxw = max($Aw, $Bw);
my $maxh = max($Ah, $Bh);
my $w = $kv && ($kv->getValue('width') || $kv->getValue('innerwidth'));
my $h = $kv && $kv->getValue('height');
my ($line1, $line2);
my ($Ax, $Ay, $Bx, $By, $Mx, $My) = (0, 0, 0, 0, 0, 0);
$w = $w->pxValue if $w;
$h = $h->pxValue if $h;
## See diagbox.pdf under Implementation
if ($M) {
if (!($w && $h)) { # size given, no need for fancy calculations
my $t = $Ah + $Mh;
my $s = $Bw + $Mw;
my $v = $s * $t - $Aw * $Bh;
my $u = $Aw * $Mh - $Mw * $Bh;
my $delta = ($u + $v) * ($u + $v) + 4 * $Aw * ($t - $Bh) * ($Mw * ($Bh - $Mh) - $Bw * $Mh);
$w = (($Bh < $t) && ($delta >= 0)
? ($u + $v + sqrt($delta)) / ($t - $Bh) / 2
: 2 * (max($Aw, $Bw) + $Mw)) unless $w;
$h = (($Aw < $s) && ($delta >= 0)
? ($u - $v - sqrt($delta)) / ($Aw - $s) / 2
: 2 * (max($Ah, $Bh) + $Mh)) unless $h; }
$w = roundto($w);
$h = roundto($h);
my ($wm, $hm) = ($w * 0.5, $h * 0.5);
if ($dir eq 'NW') {
$My = $h - $Mh;
$Bx = $w - $Bw;
$By = $h - $Bh;
$line1 = "$wm,$h $w,0";
$line2 = "0,$hm $w,0"; }
elsif ($dir eq 'SE') {
$Mx = $w - $Mw;
$Bx = $w - $Bw;
$By = $h - $Bh;
$line1 = "0,$h $w,$hm";
$line2 = "0,$h $wm,0"; }
elsif ($dir eq 'SW') {
$Ay = $h - $Ah;
$Bx = $w - $Bw;
$line1 = "0,$hm $w,$h";
$line2 = "$wm,0 $w,$h"; }
elsif ($dir eq 'NE') {
$Ay = $h - $Ah;
$Mx = $w - $Mw;
$My = $h - $Mh;
$Bx = $w - $Bw;
$line1 = "0,0 $wm,$h";
$line2 = "0,0 $w,$hm"; } }
else {
$w = 2 * $maxw unless $w;
$h = $Ah + $Bh unless $h;
$w = roundto($w);
$h = roundto($h);
$Bx = $w - $Bw;
if (($dir eq 'NW') || ($dir eq 'SE')) {
$By = $h - $Bh;
$line1 = "0,$h $w,0"; }
else {
$Ay = $h - $Ah;
$line1 = "0,0, $w,$h"; } }
my $pxppt = Dimension('1pt')->pxValue(10);
$whatsit->setProperties(
width => Dimension($w / $pxppt . 'pt'), height => Dimension($h / $pxppt . 'pt'),
A => $A, Ax => $Ax, Ay => $Ay, Aw => $Aw, Ah => $Ah,
B => $B, Bx => $Bx, By => $By, Bw => $Bw, Bh => $Bh,
M => $M, Mx => $Mx, My => $My, Mw => $Bw, Mh => $Mh,
line1 => $line1, line2 => $line2,
linewidth => ($kv && $kv->getValue('linewidth')) || '0.4',
linecolor => ($kv && $kv->getValue('linecolor')) || Black); }
);
# slashbox compatibility
DefMacro('\slashbox[][]{}{}',
'\def\@tempa{dir=SW}'
. '\ifx.#1.\else\edef\@tempa{\@tempa,width={#1}}\fi'
. '\ifx.#2.\else\edef\@tempa{\@tempa,trim={#2}}\fi'
. '\diagbox[\@tempa]{#3}{#4}');
DefMacro('\backslashbox[][]{}{}',
'\def\@tempa{dir=NW}'
. '\ifx.#1.\else\edef\@tempa{\@tempa,width={#1}}\fi'
. '\ifx.#2.\else\edef\@tempa{\@tempa,trim={#2}}\fi'
. '\diagbox[\@tempa]{#3}{#4}');
#======================================================================
1;