LaTeXML

 view release on metacpan or  search on metacpan

lib/LaTeXML/Post/MathML.pm  view on Meta::CPAN

      my $rop = realize($op);
      my $style =
        $rop->getAttribute('mathstyle') || $op->getAttribute('mathstyle');
      my $ostyle = $LaTeXML::MathML::STYLE;
      local $LaTeXML::MathML::STYLE
        = ($style && $stylestep{$style} ? $style : $LaTeXML::MathML::STYLE);
      my $result = &{ lookupPresenter('Apply', getOperatorRole($rop), $rop->getAttribute('meaning'))
      }($op, @args);
      $result = pmml_maybe_resize($node, $result);
      my $needsmathstyle = needsMathstyle($result);
      my %styleattr      = %{ ($style && ($needsmathstyle
            ? $stylemap{$ostyle}{$style}
            : $stylemap2{$ostyle}{$style})) || {} };
      $result = ['m:mstyle', {%styleattr}, $result] if keys %styleattr;
      return $result; } }
  elsif ($tag eq 'ltx:XMTok') {
    return &{ lookupPresenter('Token', $role, $node->getAttribute('meaning')) }($node); }
  elsif ($tag eq 'ltx:XMHint') {
    return &{ lookupPresenter('Hint', $role, $node->getAttribute('meaning')) }($node); }
  elsif ($tag eq 'ltx:XMArray') {
    my $width   = $node->getAttribute('width');
    my $style   = $node->getAttribute('mathstyle');
    my $vattach = $node->getAttribute('vattach');
    my $rowsep  = $node->getAttribute('rowsep') || '0pt';
    my $colsep  = $node->getAttribute('colsep') || '5pt';
    $vattach = 'axis'    if !$vattach || ($vattach eq 'middle');    # roughly MathML's axis?
    $vattach = 'bottom1' if $vattach && ($vattach eq 'top');
    my $ostyle = $LaTeXML::MathML::STYLE;
    local $LaTeXML::MathML::STYLE
      = ($style && $stylestep{$style} ? $style : $LaTeXML::MathML::STYLE);
    my @rows  = ();
    my $nrows = 0;
    my $ncols = 0;

    my @spanned = ();                                               # record columns to be skipped
    foreach my $row (element_nodes($node)) {
      my @cols = ();
      my $nc   = 0;
      $nrows++;
      foreach my $col (element_nodes($row)) {
        $nc++;
        $spanned[$nc - 1]-- if $spanned[$nc - 1];
        next                if $spanned[$nc - 1];    # Omit this mtd, if spanned by another!
        my $a    = $col->getAttribute('align');
        my $b    = $col->getAttribute('border');
        my $bc   = ($b ? join(' ', map { 'ltx_border_' . $_ } split(/\s/, $b)) : $b);
        my $th   = $col->getAttribute('thead');
        my $hc   = ($th ? join(' ', map { 'ltx_th_' . $_ } split(/\s/, $th)) : '');
        my $cl   = $col->getAttribute('class');
        my $c    = ($bc ? ($hc ? "$bc $hc" : $bc) : $hc);
        my $cs   = $col->getAttribute('colspan');
        my $rs   = $col->getAttribute('rowspan');
        my @cell = filter_row(map { pmml($_) } element_nodes($col));

        if ($rs || $cs) {                            # Note following cells to be omitted from MathML
          for (my $i = 0 ; $i < ($cs || 1) ; $i++) {
            $spanned[$nc - 1 + $i] = ($rs || 1); } }
        push(@cols, ['m:mtd', { ($a && ($a ne 'center')
                ? (columnalign => $a, class => 'ltx_align_' . $a) : ()),
              ($c || $cl ? (class      => ($c && $cl ? "$c $cl" : $c || $cl)) : ()),
              ($cs       ? (columnspan => $cs)                                : ()),
              ($rs       ? (rowspan    => $rs)                                : ()) },
            @cell]); }
      $ncols = $nc if $nc > $ncols;
      push(@rows, ['m:mtr', {}, @cols]); }
    $rowsep = undef if $nrows < 2;
    $colsep = undef if $ncols < 2;
    my $result = ['m:mtable', { ($vattach ne 'axis' ? (align => $vattach) : ()),
        ($rowsep ? (rowspacing    => $rowsep) : ()),
        ($colsep ? (columnspacing => $colsep) : ()),
        ($width  ? (width         => $width)  : ()),
        # Mozilla seems to need some encouragement?
        ($LaTeXML::MathML::STYLE eq 'display' ? (displaystyle => 'true') : ()) },
      @rows];
    my $needsmathstyle = needsMathstyle($result);
    my %styleattr      = %{ ($style && ($needsmathstyle
          ? $stylemap{$ostyle}{$style}
          : $stylemap2{$ostyle}{$style})) || {} };
    $result = ['m:mstyle', {%styleattr}, $result] if keys %styleattr;
    $result = pmml_maybe_resize($node, $result);
    return $result; }
  elsif ($tag eq 'ltx:XMText') {
    my @c = $node->childNodes;
    my $result;
    if (!$$self{nestmath}) {
      $result = pmml_row(map { pmml_text_aux($_) } @c); }
    else {
      $result = ['m:mtext', {}, $self->convertXMTextContent($doc, 1, @c)]; }
    return pmml_maybe_resize($node, $result); }
  elsif ($tag eq 'ltx:ERROR') {
    my $cl = $node->getAttribute('class');
    return ['m:merror', { class => join(' ', grep { $_ } 'ltx_ERROR', $cl) },
      ['m:mtext', {}, $node->textContent]]; }
  else {
    my $text = $node->textContent;    #  Spaces are significant here
    $text =~ s/^\s+/$NBSP/;
    $text =~ s/\s+$/$NBSP/;
    return ['m:mtext', {}, $text]; } }

sub needsMathstyle {
  no warnings 'recursion';
  my ($node) = @_;
  if (ref $node eq 'ARRAY') {
    my ($tag, $attr, @children) = @$node;
    return 1 if $tag eq 'm:mfrac';
    return 1 if $$attr{_largeop};
    return 0 if ($tag eq 'm:mstyle') && defined $$attr{displaystyle};
    return 1 if grep { needsMathstyle($_) } @children; }
  return; }

# Use mpadded instead of mrow if size has been given
# And maybe this is a convenient place to deal with frames?
sub pmml_maybe_resize {
  my ($node, $result) = @_;
  return $result unless ref $node;
  my $parent;
  # There MAY be relevant attributes on a containing XMDual (if any)!!!
  if ((ref $node) && ($node->nodeType == XML_ELEMENT_NODE)
    && ($parent = $node->parentNode) && (getQName($parent) eq 'ltx:XMDual')) { }
  else { $parent = undef; }
  my $width  = $node->getAttribute('width')   || ($parent && $parent->getAttribute('width'));



( run in 2.213 seconds using v1.01-cache-2.11-cpan-2398b32b56e )