# -*- mode: Perl -*-
# /=====================================================================\ #
# | amscd | #
# | 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. | #
# |---------------------------------------------------------------------| #
# | Thanks to the arXMLiv group for initial implementation | #
# | http://arxmliv.kwarc.info/ | #
# | Released to the Public Domain | #
# |---------------------------------------------------------------------| #
# | 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;
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Note that the amscd authors themselves point out that amcsd is limited,
# only covering array-like commutative diagrams, and they suggest
# diagram, xypic or kuvio as alternatives.
#
# However, it is just that simplicity that mkes it possible to represent
# the commutative diagram in straight latexml math, w/o resorting to
# the more general svg(-like) problems.
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DefMacro('\CD', '\@@CD\@start@alignment');
DefMacro('\endCD', '\@finish@alignment\@end@CD');
DefPrimitive('\@end@CD', sub { $_[0]->egroup; });
DefConstructor('\@@CD DigestedBody',
'#1',
beforeDigest => sub {
$_[0]->bgroup;
alignmentBindings(MatrixTemplate(), 'math', attributes => { meaning => 'commutative-diagram' });
Let(T_ALIGN, '\@cd@invisible@align');
Let("\\\\", '\@alignment@newline@noskip');
$STATE->assignMathcode('@' => 0x8000);
Let('@', '\cd@'); },
reversion => '\begin{CD}#1\end{CD}');
DefMacroI('\@cd@invisible@align', undef,
'\@close@inner@column\@close@column'
. '\@open@column\@open@inner@column');
#DefConstructorI('\@alignment@align@marker',undef,'',reversion=>'&');
DefMacro('\cd@ Token', sub {
my ($gullet, $token) = @_;
(T_CS('@' . ToString($token))); });
DefMacroI(T_CS('@>'), 'Until:> Until:>',
'&\cd@stack{>}{\rightarrowfill@}{#1}{#2}&');
DefMacroI(T_CS('@)'), 'Until:) Until:)',
'&\cd@stack{)}{\rightarrowfill@}{#1}{#2}&');
DefMacroI(T_CS('@<'), 'Until:< Until:<',
'&\cd@stack{<}{\leftarrowfill@}{#1}{#2}&');
DefMacroI(T_CS('@('), 'Until:( Until:(',
'&\cd@stack{(}{\leftarrowfill@}{#1}{#2}&');
DefMacroI(T_CS('@A'), 'Until:A Until:A',
'\cd@adjacent{A}{\Big\uparrow}{#1}{#2}&&');
DefMacroI(T_CS('@V'), 'Until:V Until:V',
'\cd@adjacent{V}{\Big\downarrow}{#1}{#2}&&');
DefMacroI(T_CS('@='), undef,
'&\@cd@equals@&');
DefMacroI(T_CS('@|'), undef,
'\Big\Vert&&');
DefMacroI(T_CS('@\vert'), undef,
'\Big\Vert&&');
DefMacroI(T_CS('@.'), undef,
'&&');
# Horizontal
DefMath('\@cd@equals@', "=", role => 'ARROW', stretchy => 'true', reversion => '@=');
# Vertical
DefMath('\@cd@bar@', "|", role => 'ARROW', font => { size => 'Big' }, reversion => '@|');
DefMath('\@cd@vert@', "\x{2225}", role => 'ARROW', font => { size => 'Big' }, reversion => '@\vert');
DefRegister('\minaw@' => Dimension('11.111pt'));
# deal with under, over & underover!
DefConstructor('\cd@stack Undigested {}{}{}', sub {
my ($document, $reversion, $op, $over, $under, %props) = @_;
my $scriptpos = $props{scriptpos};
if ($under->unlist) {
$document->openElement('ltx:XMApp', role => 'ARROW'); # Role?
$document->insertElement('ltx:XMTok', undef, role => 'SUBSCRIPTOP', scriptpos => $scriptpos);
if ($over->unlist) {
$document->openElement('ltx:XMApp'); # Role?
$document->insertElement('ltx:XMTok', undef, role => 'SUPERSCRIPTOP', scriptpos => $scriptpos);
$document->insertElement('ltx:XMArg', $op);
$document->insertElement('ltx:XMArg', $over);
$document->closeElement('ltx:XMApp'); }
else {
$document->insertElement('ltx:XMArg', $op); }
$document->insertElement('ltx:XMArg', $under);
$document->closeElement('ltx:XMApp'); }
elsif ($over->unlist) {
$document->openElement('ltx:XMApp'); # Role?
$document->insertElement('ltx:XMTok', undef, role => 'SUPERSCRIPTOP', scriptpos => $scriptpos);
$document->insertElement('ltx:XMArg', $op);
$document->insertElement('ltx:XMArg', $over);
$document->closeElement('ltx:XMApp'); }
else {
$document->insertElement('ltx:XMArg', $op); } },
properties => { scriptpos => sub { "mid" . $_[0]->getBoxingLevel; } },
reversion => '@#1{#3}#1{#4}#1');
# \cd@adj{}{}{}
# Temporary...
# Later deal with vertically centering the side things, parser issues...
#DefMacro('\cd@adjacent{}{}{}{}','{#3}{#2}{#4}');
DefConstructor('\cd@adjacent Undigested {}{}{}', sub {
my ($document, $reversion, $op, $left, $right, %props) = @_;
$document->openElement('ltx:XMWrap', role => 'ARROW'); # Role?
$document->insertElement('ltx:XMArg', $left) if $left->unlist;
$document->insertElement('ltx:XMArg', $op);
$document->insertElement('ltx:XMArg', $right) if $right->unlist;
$document->closeElement('ltx:XMWrap'); },
reversion => '@#1{#3}#1{#4}#1');
# This isn't really having the desired effect when transformed to MathML and
# displayed in Firefox.... have I got it right; has Firefox???
DefMath('\leftarrowfill@', "\x{2190}", role => 'ARROW', stretchy => 'true');
DefMath('\rightarrowfill@', "\x{2192}", role => 'ARROW', stretchy => 'true');
DefRegister('\minCDarrowwidth' => Dimension('2.5pc'));
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1;