1# /=====================================================================\ #
2# |  LaTeXML::Common::Glue                                              | #
3# | Representation of Stretchy dimensions                               | #
4# |=====================================================================| #
5# | Part of LaTeXML:                                                    | #
6# |  Public domain software, produced as part of work done by the       | #
7# |  United States Government & not subject to copyright in the US.     | #
8# |---------------------------------------------------------------------| #
9# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
10# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
11# \=========================================================ooo==U==ooo=/ #
12package LaTeXML::Common::Glue;
13use LaTeXML::Global;
14use strict;
15use warnings;
16use base qw(LaTeXML::Common::Dimension);
17use base qw(Exporter);
18our @EXPORT = (qw(&Glue));
19
20#======================================================================
21# Exported constructor.
22
23sub Glue {
24  my ($scaledpoints, $plus, $pfill, $minus, $mfill) = @_;
25  return LaTeXML::Common::Glue->new($scaledpoints, $plus, $pfill, $minus, $mfill); }
26
27#======================================================================
28
29my %fillcode = (fil => 1, fill => 2, filll => 3);    # [CONSTANT]
30my @FILL = ('', 'fil', 'fill', 'filll');             # [CONSTANT]
31
32my $num_re   = qr/\d*\.?\d*/;                        # [CONSTANT]
33my $unit_re  = qr/[a-zA-Z][a-zA-Z]/;                 # [CONSTANT]
34my $fill_re  = qr/fil|fill|filll|[a-zA-Z][a-zA-Z]/;  # [CONSTANT]
35my $plus_re  = qr/\s+plus\s*($num_re)($fill_re)/;    # [CONSTANT]
36my $minus_re = qr/\s+minus\s*($num_re)($fill_re)/;   # [CONSTANT]
37our $GLUE_re = qr/(\+?\-?$num_re)($unit_re)($plus_re)?($minus_re)?/;    # [CONSTANT]
38
39sub new {
40  my ($class, $sp, $plus, $pfill, $minus, $mfill) = @_;
41  $sp    = ToString($sp)    if ref $sp;
42  $plus  = ToString($plus)  if ref $plus;
43  $pfill = ToString($pfill) if ref $pfill;
44  $minus = ToString($minus) if ref $minus;
45  $mfill = ToString($mfill) if ref $mfill;
46  if ((!defined $plus) && (!defined $pfill) && (!defined $minus) && (!defined $mfill)) {
47    if ($sp =~ /^(\d*\.?\d*)$/) { }
48    elsif ($sp =~ /^$GLUE_re$/) {
49      my ($f, $u, $p, $pu, $m, $mu) = ($1, $2, $4, $5, $7, $8);
50      $sp = $f * $STATE->convertUnit($u);
51      if (!$pu) { }
52      elsif ($fillcode{$pu}) { $plus = $p;                            $pfill = $pu; }
53      else                   { $plus = $p * $STATE->convertUnit($pu); $pfill = 0; }
54      if (!$mu) { }
55      elsif ($fillcode{$mu}) { $minus = $m;                            $mfill = $mu; }
56      else                   { $minus = $m * $STATE->convertUnit($mu); $mfill = 0; }
57  } }
58  return bless [$sp || "0", $plus || "0", $pfill || 0, $minus || "0", $mfill || 0], $class; }
59
60#sub getStretch { $_[0]->[1]; }
61#sub getShrink  { $_[0]->[2]; }
62
63sub toString {
64  my ($self) = @_;
65  my ($sp, $plus, $pfill, $minus, $mfill) = @$self;
66  my $string = LaTeXML::Common::Dimension::pointformat($sp);
67  $string .= ' plus ' . ($pfill
68    ? $plus . $FILL[$pfill]
69    : LaTeXML::Common::Dimension::pointformat($plus))
70    if $plus != 0;
71  $string .= ' minus ' . ($mfill
72    ? $minus . $FILL[$mfill]
73    : LaTeXML::Common::Dimension::pointformat($minus))
74    if $minus != 0;
75  return $string; }
76
77sub toAttribute {
78  my ($self) = @_;
79  my ($sp, $plus, $pfill, $minus, $mfill) = @$self;
80  my $string = LaTeXML::Common::Dimension::attributeformat($sp);
81  $string .= ' plus ' . ($pfill
82    ? $plus . $FILL[$pfill]
83    : LaTeXML::Common::Dimension::attributeformat($plus))
84    if $plus != 0;
85  $string .= ' minus ' . ($mfill
86    ? $minus . $FILL[$mfill]
87    : LaTeXML::Common::Dimension::attributeformat($minus))
88    if $minus != 0;
89  return $string; }
90
91sub negate {
92  my ($self) = @_;
93  my ($pts, $p, $pf, $m, $mf) = @$self;
94  return (ref $self)->new(-$pts, -$p, $pf, -$m, $mf); }
95
96sub add {
97  my ($self, $other) = @_;
98  my ($pts, $p, $pf, $m, $mf) = @$self;
99  if (ref $other eq 'LaTeXML::Common::Glue') {
100    my ($pts2, $p2, $pf2, $m2, $mf2) = @$other;
101    $pts += $pts2;
102    if ($pf == $pf2) { $p += $p2; }
103    elsif ($pf < $pf2) { $p = $p2; $pf = $pf2; }
104    if ($mf == $mf2) { $m += $m2; }
105    elsif ($mf < $mf2) { $m = $m2; $mf = $mf2; }
106    return (ref $self)->new($pts, $p, $pf, $m, $mf); }
107  else {
108    return (ref $self)->new($pts + $other->valueOf, $p, $pf, $m, $mf); } }
109
110sub multiply {
111  my ($self, $other) = @_;
112  my ($pts, $p, $pf, $m, $mf) = @$self;
113  $other = $other->valueOf if ref $other;
114  return (ref $self)->new($pts * $other, $p * $other, $pf, $m * $other, $mf); }
115
116sub divide {
117  my ($self, $other) = @_;
118  my ($pts, $p, $pf, $m, $mf) = @$self;
119  $other = $other->valueOf if ref $other;
120  return (ref $self)->new($pts / $other, $p / $other, $pf, $m / $other, $mf); }
121
122sub divideround {
123  my ($self, $other) = @_;
124  my ($pts, $p, $pf, $m, $mf) = @$self;
125  $other = $other->valueOf if ref $other;
126  return (ref $self)->new($pts / $other, $p / $other, $pf, $m / $other, $mf); }
127
128sub stringify {
129  my ($self) = @_;
130  return "Glue[" . join(',', @$self) . "]"; }
131
132#======================================================================
1331;
134
135__END__
136
137=pod
138
139=head1 NAME
140
141C<LaTeXML::Common::Glue> - representation of glue, skips, stretchy dimensions;
142extends L<LaTeXML::Common::Dimension>.
143
144=head2 Exported functions
145
146=over 4
147
148=item C<< $glue = Glue($gluespec); >>
149
150=item C<< $glue = Glue($sp,$plus,$pfill,$minus,$mfill); >>
151
152Creates a Glue object.  C<$gluespec> can be a string in the
153form that TeX recognizes (number units optional plus and minus parts).
154Alternatively, the dimension, plus and minus parts can be given separately:
155C<$pfill> and C<$mfill> are 0 (when the C<$plus> or C<$minus> part is in sp)
156or 1,2,3 for fil, fill or filll.
157
158=back
159
160=head1 AUTHOR
161
162Bruce Miller <bruce.miller@nist.gov>
163
164=head1 COPYRIGHT
165
166Public domain software, produced as part of work done by the
167United States Government & not subject to copyright in the US.
168
169=cut
170
171