LCOV - code coverage report
Current view: top level - starmath/source - node.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1118 1601 69.8 %
Date: 2015-06-13 12:38:46 Functions: 117 156 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "node.hxx"
      22             : #include "rect.hxx"
      23             : #include "symbol.hxx"
      24             : #include "smmod.hxx"
      25             : #include "document.hxx"
      26             : #include "view.hxx"
      27             : #include "mathtype.hxx"
      28             : #include "tmpdevice.hxx"
      29             : #include "visitors.hxx"
      30             : 
      31             : #include <comphelper/string.hxx>
      32             : #include <tools/color.hxx>
      33             : #include <tools/fract.hxx>
      34             : #include <tools/gen.hxx>
      35             : #include <vcl/outdev.hxx>
      36             : 
      37             : #include <math.h>
      38             : #include <float.h>
      39             : #include <vector>
      40             : 
      41       15756 : SmNode::SmNode(SmNodeType eNodeType, const SmToken &rNodeToken)
      42             :     : aNodeToken( rNodeToken )
      43             :     , eType( eNodeType )
      44             :     , eScaleMode( SCALE_NONE )
      45             :     , eRectHorAlign( RHA_LEFT )
      46             :     , nFlags( 0 )
      47             :     , nAttributes( 0 )
      48             :     , bIsPhantom( false )
      49             :     , bIsSelected( false )
      50             :     , nAccIndex( -1 )
      51       15756 :     , aParentNode( NULL )
      52             : {
      53       15756 : }
      54             : 
      55             : 
      56       15735 : SmNode::~SmNode()
      57             : {
      58       15735 : }
      59             : 
      60             : 
      61           0 : bool SmNode::IsVisible() const
      62             : {
      63           0 :     return false;
      64             : }
      65             : 
      66             : 
      67           0 : sal_uInt16 SmNode::GetNumSubNodes() const
      68             : {
      69           0 :     return 0;
      70             : }
      71             : 
      72             : 
      73           0 : SmNode * SmNode::GetSubNode(sal_uInt16 /*nIndex*/)
      74             : {
      75           0 :     return NULL;
      76             : }
      77             : 
      78             : 
      79        5865 : SmNode * SmNode::GetLeftMost()
      80             :     //  returns leftmost node of current subtree.
      81             :     //! (this assumes the one with index 0 is always the leftmost subnode
      82             :     //! for the current node).
      83             : {
      84        5865 :     SmNode *pNode = GetNumSubNodes() > 0 ?
      85        5865 :                         GetSubNode(0) : NULL;
      86             : 
      87        5865 :     return pNode ? pNode->GetLeftMost() : this;
      88             : }
      89             : 
      90             : 
      91           0 : void SmNode::SetPhantom(bool bIsPhantomP)
      92             : {
      93           0 :     if (! (Flags() & FLG_VISIBLE))
      94           0 :         bIsPhantom = bIsPhantomP;
      95             : 
      96             :     SmNode *pNode;
      97           0 :     sal_uInt16  nSize = GetNumSubNodes();
      98           0 :     for (sal_uInt16 i = 0; i < nSize; i++)
      99           0 :         if (NULL != (pNode = GetSubNode(i)))
     100           0 :             pNode->SetPhantom(bIsPhantom);
     101           0 : }
     102             : 
     103             : 
     104           0 : void SmNode::SetColor(const Color& rColor)
     105             : {
     106           0 :     if (! (Flags() & FLG_COLOR))
     107           0 :         GetFont().SetColor(rColor);
     108             : 
     109             :     SmNode *pNode;
     110           0 :     sal_uInt16  nSize = GetNumSubNodes();
     111           0 :     for (sal_uInt16 i = 0; i < nSize; i++)
     112           0 :         if (NULL != (pNode = GetSubNode(i)))
     113           0 :             pNode->SetColor(rColor);
     114           0 : }
     115             : 
     116             : 
     117          49 : void SmNode::SetAttribut(sal_uInt16 nAttrib)
     118             : {
     119          49 :     if (
     120          98 :         (nAttrib == ATTR_BOLD && !(Flags() & FLG_BOLD)) ||
     121          49 :         (nAttrib == ATTR_ITALIC && !(Flags() & FLG_ITALIC))
     122             :        )
     123             :     {
     124          49 :         nAttributes |= nAttrib;
     125             :     }
     126             : 
     127             :     SmNode *pNode;
     128          49 :     sal_uInt16 nSize = GetNumSubNodes();
     129          97 :     for (sal_uInt16 i = 0; i < nSize; i++)
     130          48 :         if (NULL != (pNode = GetSubNode(i)))
     131          24 :             pNode->SetAttribut(nAttrib);
     132          49 : }
     133             : 
     134             : 
     135           0 : void SmNode::ClearAttribut(sal_uInt16 nAttrib)
     136             : {
     137           0 :     if (
     138           0 :         (nAttrib == ATTR_BOLD && !(Flags() & FLG_BOLD)) ||
     139           0 :         (nAttrib == ATTR_ITALIC && !(Flags() & FLG_ITALIC))
     140             :        )
     141             :     {
     142           0 :         nAttributes &= ~nAttrib;
     143             :     }
     144             : 
     145             :     SmNode *pNode;
     146           0 :     sal_uInt16 nSize = GetNumSubNodes();
     147           0 :     for (sal_uInt16 i = 0; i < nSize; i++)
     148           0 :         if (NULL != (pNode = GetSubNode(i)))
     149           0 :             pNode->ClearAttribut(nAttrib);
     150           0 : }
     151             : 
     152             : 
     153          12 : void SmNode::SetFont(const SmFace &rFace)
     154             : {
     155          12 :     if (!(Flags() & FLG_FONT))
     156          12 :         GetFont() = rFace;
     157             : 
     158             :     SmNode *pNode;
     159          12 :     sal_uInt16  nSize = GetNumSubNodes();
     160          24 :     for (sal_uInt16 i = 0; i < nSize; i++)
     161          12 :         if (NULL != (pNode = GetSubNode(i)))
     162           6 :             pNode->SetFont(rFace);
     163          12 : }
     164             : 
     165             : 
     166         228 : void SmNode::SetFontSize(const Fraction &rSize, FontSizeType nType)
     167             :     //! 'rSize' is in units of pts
     168             : {
     169         228 :     Size  aFntSize;
     170             : 
     171         228 :     if (!(Flags() & FLG_SIZE))
     172             :     {
     173             :         Fraction  aVal (SmPtsTo100th_mm(rSize.GetNumerator()),
     174         228 :                         rSize.GetDenominator());
     175         228 :         long      nHeight = (long)aVal;
     176             : 
     177         228 :         aFntSize = GetFont().GetSize();
     178         228 :         aFntSize.Width() = 0;
     179         228 :         switch(nType)
     180             :         {
     181             :             case FontSizeType::ABSOLUT:
     182         228 :                 aFntSize.Height() = nHeight;
     183         228 :                 break;
     184             : 
     185             :             case FontSizeType::PLUS:
     186           0 :                 aFntSize.Height() += nHeight;
     187           0 :                 break;
     188             : 
     189             :             case FontSizeType::MINUS:
     190           0 :                 aFntSize.Height() -= nHeight;
     191           0 :                 break;
     192             : 
     193             :             case FontSizeType::MULTIPLY:
     194           0 :                 aFntSize.Height()   = (long) (Fraction(aFntSize.Height()) * rSize);
     195           0 :                 break;
     196             : 
     197             :             case FontSizeType::DIVIDE:
     198           0 :                 if (rSize != Fraction(0L))
     199           0 :                     aFntSize.Height()   = (long) (Fraction(aFntSize.Height()) / rSize);
     200           0 :                 break;
     201             :             default:
     202           0 :                 break;
     203             :         }
     204             : 
     205             :         // check the requested size against maximum value
     206         228 :         static int const    nMaxVal = SmPtsTo100th_mm(128);
     207         228 :         if (aFntSize.Height() > nMaxVal)
     208           0 :             aFntSize.Height() = nMaxVal;
     209             : 
     210         228 :         GetFont().SetSize(aFntSize);
     211             :     }
     212             : 
     213             :     SmNode *pNode;
     214         228 :     sal_uInt16  nSize = GetNumSubNodes();
     215         576 :     for (sal_uInt16 i = 0;  i < nSize;  i++)
     216         348 :         if (NULL != (pNode = GetSubNode(i)))
     217         162 :             pNode->SetFontSize(rSize, nType);
     218         228 : }
     219             : 
     220             : 
     221        3846 : void SmNode::SetSize(const Fraction &rSize)
     222             : {
     223        3846 :     GetFont() *= rSize;
     224             : 
     225             :     SmNode *pNode;
     226        3846 :     sal_uInt16  nSize = GetNumSubNodes();
     227        5285 :     for (sal_uInt16 i = 0;  i < nSize;  i++)
     228        1439 :         if (NULL != (pNode = GetSubNode(i)))
     229        1317 :             pNode->SetSize(rSize);
     230        3846 : }
     231             : 
     232             : 
     233         996 : void SmNode::SetRectHorAlign(RectHorAlign eHorAlign, bool bApplyToSubTree )
     234             : {
     235         996 :     if (!(Flags() & FLG_HORALIGN))
     236         996 :         eRectHorAlign = eHorAlign;
     237             : 
     238         996 :     if (bApplyToSubTree)
     239             :     {
     240             :         SmNode *pNode;
     241         102 :         sal_uInt16  nSize = GetNumSubNodes();
     242         102 :         for (sal_uInt16 i = 0; i < nSize; i++)
     243           0 :             if (NULL != (pNode = GetSubNode(i)))
     244           0 :                 pNode->SetRectHorAlign(eHorAlign);
     245             :     }
     246         996 : }
     247             : 
     248             : 
     249        7354 : void SmNode::PrepareAttributes()
     250             : {
     251        7354 :     GetFont().SetWeight((Attributes() & ATTR_BOLD)   ? WEIGHT_BOLD   : WEIGHT_NORMAL);
     252        7354 :     GetFont().SetItalic((Attributes() & ATTR_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE);
     253        7354 : }
     254             : 
     255             : 
     256       16185 : void SmNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
     257             : {
     258       16185 :     bIsPhantom  = false;
     259       16185 :     nFlags      = 0;
     260       16185 :     nAttributes = 0;
     261             : 
     262       16185 :     switch (rFormat.GetHorAlign())
     263           0 :     {   case AlignLeft:     eRectHorAlign = RHA_LEFT;   break;
     264       16020 :         case AlignCenter:   eRectHorAlign = RHA_CENTER; break;
     265         165 :         case AlignRight:    eRectHorAlign = RHA_RIGHT;  break;
     266             :     }
     267             : 
     268       16185 :     GetFont() = rFormat.GetFont(FNT_MATH);
     269             :     OSL_ENSURE( GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE,
     270             :             "unexpected CharSet" );
     271       16185 :     GetFont().SetWeight(WEIGHT_NORMAL);
     272       16185 :     GetFont().SetItalic(ITALIC_NONE);
     273             : 
     274             :     SmNode *pNode;
     275       16185 :     sal_uInt16      nSize = GetNumSubNodes();
     276       34236 :     for (sal_uInt16 i = 0; i < nSize; i++)
     277       18051 :         if (NULL != (pNode = GetSubNode(i)))
     278       14219 :             pNode->Prepare(rFormat, rDocShell);
     279       16185 : }
     280             : 
     281           0 : sal_uInt16 SmNode::FindIndex() const
     282             : {
     283           0 :     const SmStructureNode* pParent = GetParent();
     284           0 :     if (!pParent) { return 0; }
     285             : 
     286           0 :     for (sal_uInt16 i = 0; i < pParent->GetNumSubNodes(); ++i) {
     287           0 :         if (pParent->GetSubNode(i) == this) {
     288           0 :             return i;
     289             :         }
     290             :     }
     291             : 
     292             :     DBG_ASSERT(false, "Connection between parent and child is inconsistent.");
     293           0 :     return 0;
     294             : }
     295             : 
     296             : 
     297       30653 : void SmNode::Move(const Point& rPosition)
     298             : {
     299       30653 :     if (rPosition.X() == 0  &&  rPosition.Y() == 0)
     300       30659 :         return;
     301             : 
     302       30647 :     SmRect::Move(rPosition);
     303             : 
     304             :     SmNode *pNode;
     305       30647 :     sal_uInt16  nSize = GetNumSubNodes();
     306       62855 :     for (sal_uInt16 i = 0;  i < nSize;  i++)
     307       32208 :         if (NULL != (pNode = GetSubNode(i)))
     308       22845 :             pNode->Move(rPosition);
     309             : }
     310             : 
     311             : 
     312           0 : void SmNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
     313             : {
     314             :     SmNode *pNode;
     315           0 :     sal_uInt16  nSize = GetNumSubNodes();
     316           0 :     for (sal_uInt16 i = 0;  i < nSize;  i++)
     317           0 :         if (NULL != (pNode = GetSubNode(i)))
     318           0 :             pNode->Arrange(rDev, rFormat);
     319           0 : }
     320             : 
     321           6 : void SmNode::CreateTextFromNode(OUString &rText)
     322             : {
     323             :     SmNode *pNode;
     324           6 :     sal_uInt16  nSize = GetNumSubNodes();
     325           6 :     if (nSize > 1)
     326           0 :         rText += "{";
     327          12 :     for (sal_uInt16 i = 0;  i < nSize;  i++)
     328           6 :         if (NULL != (pNode = GetSubNode(i)))
     329           6 :             pNode->CreateTextFromNode(rText);
     330           6 :     if (nSize > 1)
     331             :     {
     332           0 :         rText = comphelper::string::stripEnd(rText, ' ');
     333           0 :         rText += "} ";
     334             :     }
     335           6 : }
     336             : 
     337             : 
     338           0 : void SmNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong /*nWidth*/)
     339             : {
     340           0 : }
     341             : 
     342             : 
     343           0 : void SmNode::AdaptToY(const OutputDevice &/*rDev*/, sal_uLong /*nHeight*/)
     344             : {
     345           0 : }
     346             : 
     347             : 
     348          81 : const SmNode * SmNode::FindTokenAt(sal_uInt16 nRow, sal_uInt16 nCol) const
     349             :     // returns (first) ** visible ** (sub)node with the tokens text at
     350             :     // position 'nRow', 'nCol'.
     351             :     //! (there should be exactly one such node if any)
     352             : {
     353         162 :     if (    IsVisible()
     354           8 :         &&  nRow == GetToken().nRow
     355          89 :         &&  nCol >= GetToken().nCol  &&  nCol < GetToken().nCol + GetToken().aText.getLength())
     356           8 :         return this;
     357             :     else
     358             :     {
     359          73 :         sal_uInt16  nNumSubNodes = GetNumSubNodes();
     360         105 :         for (sal_uInt16  i = 0;  i < nNumSubNodes;  i++)
     361          57 :         {   const SmNode *pNode = GetSubNode(i);
     362             : 
     363          57 :             if (!pNode)
     364           0 :                 continue;
     365             : 
     366          57 :             const SmNode *pResult = pNode->FindTokenAt(nRow, nCol);
     367          57 :             if (pResult)
     368          25 :                 return pResult;
     369             :         }
     370             :     }
     371             : 
     372          48 :     return 0;
     373             : }
     374             : 
     375             : 
     376           0 : const SmNode * SmNode::FindRectClosestTo(const Point &rPoint) const
     377             : {
     378           0 :     long          nDist   = LONG_MAX;
     379           0 :     const SmNode *pResult = 0;
     380             : 
     381           0 :     if (IsVisible())
     382           0 :         pResult = this;
     383             :     else
     384             :     {
     385           0 :         sal_uInt16  nNumSubNodes = GetNumSubNodes();
     386           0 :         for (sal_uInt16  i = 0;  i < nNumSubNodes;  i++)
     387           0 :         {   const SmNode *pNode = GetSubNode(i);
     388             : 
     389           0 :             if (!pNode)
     390           0 :                 continue;
     391             : 
     392             :             long  nTmp;
     393           0 :             const SmNode *pFound = pNode->FindRectClosestTo(rPoint);
     394           0 :             if (pFound  &&  (nTmp = pFound->OrientedDist(rPoint)) < nDist)
     395           0 :             {   nDist   = nTmp;
     396           0 :                 pResult = pFound;
     397             : 
     398             :                 // quit immediately if 'rPoint' is inside the *should not
     399             :                 // overlap with other rectangles* part.
     400             :                 // This (partly) serves for getting the attributes in eg
     401             :                 // "bar overstrike a".
     402             :                 // ('nDist < 0' is used as *quick shot* to avoid evaluation of
     403             :                 // the following expression, where the result is already determined)
     404           0 :                 if (nDist < 0  &&  pFound->IsInsideRect(rPoint))
     405           0 :                     break;
     406             :             }
     407             :         }
     408             :     }
     409             : 
     410           0 :     return pResult;
     411             : }
     412             : 
     413           0 : void SmNode::GetAccessibleText( OUStringBuffer &/*rText*/ ) const
     414             : {
     415             :     SAL_WARN("starmath", "SmNode: GetAccessibleText not overridden");
     416           0 : }
     417             : 
     418           0 : const SmNode * SmNode::FindNodeWithAccessibleIndex(sal_Int32 nAccIdx) const
     419             : {
     420           0 :     const SmNode *pResult = 0;
     421             : 
     422           0 :     sal_Int32 nIdx = GetAccessibleIndex();
     423           0 :     OUStringBuffer aTxt;
     424           0 :     if (nIdx >= 0)
     425           0 :         GetAccessibleText( aTxt );  // get text if used in following 'if' statement
     426             : 
     427           0 :     if (nIdx >= 0
     428           0 :         &&  nIdx <= nAccIdx  &&  nAccIdx < nIdx + aTxt.getLength())
     429           0 :         pResult = this;
     430             :     else
     431             :     {
     432           0 :         sal_uInt16  nNumSubNodes = GetNumSubNodes();
     433           0 :         for (sal_uInt16  i = 0;  i < nNumSubNodes;  i++)
     434             :         {
     435           0 :             const SmNode *pNode = GetSubNode(i);
     436           0 :             if (!pNode)
     437           0 :                 continue;
     438             : 
     439           0 :             pResult = pNode->FindNodeWithAccessibleIndex(nAccIdx);
     440           0 :             if (pResult)
     441           0 :                 return pResult;
     442             :         }
     443             :     }
     444             : 
     445           0 :     return pResult;
     446             : }
     447             : 
     448             : #ifdef DEBUG_ENABLE_DUMPASDOT
     449             : void SmNode::DumpAsDot(std::ostream &out, OUString* label, int number, int& id, int parent) const
     450             : {
     451             :     //If this is the root start the file
     452             :     if(number == -1){
     453             :         out<<"digraph {"<<std::endl;
     454             :         if(label){
     455             :             out<<"labelloc = \"t\";"<<std::endl;
     456             :             OUString eq(*label);
     457             :             //CreateTextFromNode(eq);
     458             :             eq = eq.replaceAll("\n", " ");
     459             :             eq = eq.replaceAll("\\", "\\\\");
     460             :             eq = eq.replaceAll("\"", "\\\"");
     461             :             out<<"label= \"Equation: \\\"";
     462             :             out<< OUStringToOString(eq, RTL_TEXTENCODING_UTF8).getStr();
     463             :             out<<"\\\"\";"<<std::endl;
     464             :         }
     465             :     }
     466             : 
     467             :     //Some how out<<(int)this; doesn't work... So we  do this nasty workaround...
     468             :     char strid[100];
     469             :     sprintf(strid, "%i", id);
     470             : 
     471             :     char strnr[100];
     472             :     sprintf(strnr, "%i", number);
     473             : 
     474             :     //Dump connection to this node
     475             :     if( parent != -1 ){
     476             :         char pid[100];
     477             :         sprintf(pid, "%i", parent);
     478             :         out<<"n"<<pid<<" -> n"<<strid<<" [label=\""<<strnr<<"\"];"<<std::endl;
     479             :     //If doesn't have parent and isn't a rootnode:
     480             :     } else if(number != -1) {
     481             :         out<<"orphaned -> n"<<strid<<" [label=\""<<strnr<<"\"];"<<std::endl;
     482             :     }
     483             : 
     484             :     //Dump this node
     485             :     out<<"n"<< strid<<" [label=\"";
     486             :     switch( GetType() ) {
     487             :         case NTABLE:           out<<"SmTableNode"; break;
     488             :         case NBRACE:           out<<"SmBraceNode"; break;
     489             :         case NBRACEBODY:       out<<"SmBracebodyNode"; break;
     490             :         case NOPER:            out<<"SmOperNode"; break;
     491             :         case NALIGN:           out<<"SmAlignNode"; break;
     492             :         case NATTRIBUT:        out<<"SmAttributNode"; break;
     493             :         case NFONT:            out<<"SmFontNode"; break;
     494             :         case NUNHOR:           out<<"SmUnHorNode"; break;
     495             :         case NBINHOR:          out<<"SmBinHorNode"; break;
     496             :         case NBINVER:          out<<"SmBinVerNode"; break;
     497             :         case NBINDIAGONAL:     out<<"SmBinDiagonalNode"; break;
     498             :         case NSUBSUP:          out<<"SmSubSupNode"; break;
     499             :         case NMATRIX:          out<<"SmMatrixNode"; break;
     500             :         case NPLACE:           out<<"SmPlaceNode"; break;
     501             :         case NTEXT:
     502             :             out<<"SmTextNode: ";
     503             :             out<< OUStringToOString(((SmTextNode*)this)->GetText(), RTL_TEXTENCODING_UTF8).getStr();
     504             :             break;
     505             :         case NSPECIAL:             out<<"SmSpecialNode"; break;
     506             :         case NGLYPH_SPECIAL:   out<<"SmGlyphSpecialNode"; break;
     507             :         case NMATH:
     508             :             out<<"SmMathSymbolNode: ";
     509             :             out<< OUStringToOString(((SmMathSymbolNode*)this)->GetText(), RTL_TEXTENCODING_UTF8).getStr();
     510             :             break;
     511             :         case NBLANK:           out<<"SmBlankNode"; break;
     512             :         case NERROR:           out<<"SmErrorNode"; break;
     513             :         case NLINE:            out<<"SmLineNode"; break;
     514             :         case NEXPRESSION:      out<<"SmExpressionNode"; break;
     515             :         case NPOLYLINE:        out<<"SmPolyLineNode"; break;
     516             :         case NROOT:            out<<"SmRootNode"; break;
     517             :         case NROOTSYMBOL:      out<<"SmRootSymbolNode"; break;
     518             :         case NRECTANGLE:       out<<"SmRectangleNode"; break;
     519             :         case NVERTICAL_BRACE:  out<<"SmVerticalBraceNode"; break;
     520             :         case NMATHIDENT:       out<<"SmMathIdentifierNode"; break;
     521             :         case NINTDYNSYMBOL:            out<<"SmDynIntegralSymbolNode"; break;
     522             :         case NINTDYN:            out<<"SmDynIntegralNode"; break;
     523             :         default:
     524             :             out<<"Unknown Node";
     525             :     }
     526             :     out<<"\"";
     527             :     if(IsSelected())
     528             :         out<<", style=dashed";
     529             :     out<<"];"<<std::endl;
     530             : 
     531             :     //Dump subnodes
     532             :     int myid = id;
     533             :     const SmNode *pNode;
     534             :     sal_uInt16 nSize = GetNumSubNodes();
     535             :     for (sal_uInt16 i = 0; i < nSize;  i++)
     536             :         if (NULL != (pNode = GetSubNode(i)))
     537             :             pNode->DumpAsDot(out, NULL, i, ++id, myid);
     538             : 
     539             :     //If this is the root end the file
     540             :     if( number == -1 )
     541             :         out<<"}"<<std::endl;
     542             : }
     543             : #endif /* DEBUG_ENABLE_DUMPASDOT */
     544             : 
     545           0 : long SmNode::GetFormulaBaseline() const
     546             : {
     547             :     SAL_WARN("starmath", "This dummy implementation should not have been called.");
     548           0 :     return 0;
     549             : }
     550             : 
     551             : 
     552             : 
     553           0 : SmStructureNode::SmStructureNode( const SmStructureNode &rNode ) :
     554           0 :     SmNode( rNode.GetType(), rNode.GetToken() )
     555             : {
     556             :     size_t i;
     557           0 :     for (i = 0;  i < aSubNodes.size();  i++)
     558           0 :         delete aSubNodes[i];
     559           0 :     aSubNodes.resize(0);
     560             : 
     561           0 :     auto nSize = rNode.aSubNodes.size();
     562           0 :     aSubNodes.resize( nSize );
     563           0 :     for (i = 0;  i < nSize;  ++i)
     564             :     {
     565           0 :         SmNode *pNode = rNode.aSubNodes[i];
     566           0 :         aSubNodes[i] = pNode ? new SmNode( *pNode ) : 0;
     567             :     }
     568           0 :     ClaimPaternity();
     569           0 : }
     570             : 
     571             : 
     572       13532 : SmStructureNode::~SmStructureNode()
     573             : {
     574             :     SmNode *pNode;
     575             : 
     576       24582 :     for (sal_uInt16 i = 0;  i < GetNumSubNodes();  i++)
     577       17816 :         if (NULL != (pNode = GetSubNode(i)))
     578       13925 :             delete pNode;
     579        6766 : }
     580             : 
     581             : 
     582           0 : SmStructureNode & SmStructureNode::operator = ( const SmStructureNode &rNode )
     583             : {
     584           0 :     SmNode::operator = ( rNode );
     585             : 
     586             :     size_t i;
     587           0 :     for (i = 0;  i < aSubNodes.size();  i++)
     588           0 :         delete aSubNodes[i];
     589           0 :     aSubNodes.resize(0);
     590             : 
     591           0 :     auto nSize = rNode.aSubNodes.size();
     592           0 :     aSubNodes.resize( nSize );
     593           0 :     for (i = 0;  i < nSize;  ++i)
     594             :     {
     595           0 :         SmNode *pNode = rNode.aSubNodes[i];
     596           0 :         aSubNodes[i] = pNode ? new SmNode( *pNode ) : 0;
     597             :     }
     598             : 
     599           0 :     ClaimPaternity();
     600             : 
     601           0 :     return *this;
     602             : }
     603             : 
     604             : 
     605        3021 : void SmStructureNode::SetSubNodes(SmNode *pFirst, SmNode *pSecond, SmNode *pThird)
     606             : {
     607        3021 :     size_t nSize = pThird ? 3 : (pSecond ? 2 : (pFirst ? 1 : 0));
     608        3021 :     aSubNodes.resize( nSize );
     609        3021 :     if (pFirst)
     610        2509 :         aSubNodes[0] = pFirst;
     611        3021 :     if (pSecond)
     612        2654 :         aSubNodes[1] = pSecond;
     613        3021 :     if (pThird)
     614        1880 :         aSubNodes[2] = pThird;
     615             : 
     616        3021 :     ClaimPaternity();
     617        3021 : }
     618             : 
     619             : 
     620        4044 : void SmStructureNode::SetSubNodes(const SmNodeArray &rNodeArray)
     621             : {
     622        4044 :     aSubNodes = rNodeArray;
     623        4044 :     ClaimPaternity();
     624        4044 : }
     625             : 
     626             : 
     627          73 : bool SmStructureNode::IsVisible() const
     628             : {
     629          73 :     return false;
     630             : }
     631             : 
     632             : 
     633       92507 : sal_uInt16 SmStructureNode::GetNumSubNodes() const
     634             : {
     635       92507 :     return (sal_uInt16) aSubNodes.size();
     636             : }
     637             : 
     638             : 
     639      216828 : SmNode * SmStructureNode::GetSubNode(sal_uInt16 nIndex)
     640             : {
     641      216828 :     return aSubNodes[nIndex];
     642             : }
     643             : 
     644             : 
     645           0 : void SmStructureNode::GetAccessibleText( OUStringBuffer &rText ) const
     646             : {
     647           0 :     sal_uInt16 nNodes = GetNumSubNodes();
     648           0 :     for (sal_uInt16 i = 0;  i < nNodes;  ++i)
     649             :     {
     650           0 :         SmNode *pNode = const_cast<SmStructureNode *>(this)->GetSubNode(i);
     651           0 :         if (pNode)
     652             :         {
     653           0 :             if (pNode->IsVisible())
     654           0 :                 static_cast<SmStructureNode *>(pNode)->nAccIndex = rText.getLength();
     655           0 :             pNode->GetAccessibleText( rText );
     656             :         }
     657             :     }
     658           0 : }
     659             : 
     660             : 
     661             : 
     662             : 
     663           8 : bool SmVisibleNode::IsVisible() const
     664             : {
     665           8 :     return true;
     666             : }
     667             : 
     668             : 
     669       36402 : sal_uInt16 SmVisibleNode::GetNumSubNodes() const
     670             : {
     671       36402 :     return 0;
     672             : }
     673             : 
     674             : 
     675           0 : SmNode * SmVisibleNode::GetSubNode(sal_uInt16 /*nIndex*/)
     676             : {
     677           0 :     return NULL;
     678             : }
     679             : 
     680             : 
     681             : 
     682             : 
     683           0 : void SmGraphicNode::GetAccessibleText( OUStringBuffer &rText ) const
     684             : {
     685           0 :     rText.append(GetToken().aText);
     686           0 : }
     687             : 
     688             : 
     689             : 
     690             : 
     691           5 : void SmExpressionNode::CreateTextFromNode(OUString &rText)
     692             : {
     693             :     SmNode *pNode;
     694           5 :     sal_uInt16  nSize = GetNumSubNodes();
     695           5 :     if (nSize > 1)
     696           2 :         rText += "{";
     697          14 :     for (sal_uInt16 i = 0;  i < nSize;  i++)
     698           9 :         if (NULL != (pNode = GetSubNode(i)))
     699             :         {
     700           9 :             pNode->CreateTextFromNode(rText);
     701             :             //Just a bit of foo to make unary +asd -asd +-asd -+asd look nice
     702           9 :             if (pNode->GetType() == NMATH)
     703           4 :                 if ((nSize != 2) ||
     704           0 :                     ( !rText.endsWith("+") && !rText.endsWith("-") ))
     705           2 :                     rText += " ";
     706             :         }
     707             : 
     708           5 :     if (nSize > 1)
     709             :     {
     710           2 :         rText = comphelper::string::stripEnd(rText, ' ');
     711           2 :         rText += "} ";
     712             :     }
     713           5 : }
     714             : 
     715             : 
     716             : 
     717             : 
     718        1173 : void SmTableNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
     719             :     // arranges all subnodes in one column
     720             : {
     721             :     SmNode *pNode;
     722        1173 :     sal_uInt16  nSize   = GetNumSubNodes();
     723             : 
     724             :     // make distance depend on font size
     725        1173 :     long  nDist = +(rFormat.GetDistance(DIS_VERTICAL)
     726        1173 :                     * GetFont().GetSize().Height()) / 100L;
     727             : 
     728        1173 :     if (nSize < 1)
     729        1173 :         return;
     730             : 
     731             :     // arrange subnodes and get maximum width of them
     732        1173 :     long  nMaxWidth = 0,
     733             :           nTmp;
     734             :     sal_uInt16 i;
     735        2444 :     for (i = 0; i < nSize;  i++)
     736        1271 :         if (NULL != (pNode = GetSubNode(i)))
     737        1271 :         {   pNode->Arrange(rDev, rFormat);
     738        1271 :             if ((nTmp = pNode->GetItalicWidth()) > nMaxWidth)
     739        1216 :                 nMaxWidth = nTmp;
     740             :         }
     741             : 
     742        1173 :     Point  aPos;
     743        1173 :     SmRect::operator = (SmRect(nMaxWidth, 1));
     744        2444 :     for (i = 0;  i < nSize;  i++)
     745        1271 :     {   if (NULL != (pNode = GetSubNode(i)))
     746        1271 :         {   const SmRect &rNodeRect = pNode->GetRect();
     747        1271 :             const SmNode *pCoNode   = pNode->GetLeftMost();
     748        1271 :             RectHorAlign  eHorAlign = pCoNode->GetRectHorAlign();
     749             : 
     750             :             aPos = rNodeRect.AlignTo(*this, RP_BOTTOM,
     751        1271 :                         eHorAlign, RVA_BASELINE);
     752        1271 :             if (i)
     753          98 :                 aPos.Y() += nDist;
     754        1271 :             pNode->MoveTo(aPos);
     755        1271 :             ExtendBy(rNodeRect, nSize > 1 ? RCP_NONE : RCP_ARG);
     756             :         }
     757             :     }
     758             :     // #i972#
     759        1173 :     if (HasBaseline())
     760        1006 :         nFormulaBaseline = GetBaseline();
     761             :     else
     762             :     {
     763         167 :         SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
     764         167 :         aTmpDev.SetFont(GetFont());
     765             : 
     766             :         SmRect aRect = (SmRect(aTmpDev, &rFormat, OUString("a"),
     767         167 :                                GetFont().GetBorderWidth()));
     768         167 :         nFormulaBaseline = GetAlignM();
     769             :         // move from middle position by constant - distance
     770             :         // between middle and baseline for single letter
     771         167 :         nFormulaBaseline += aRect.GetBaseline() - aRect.GetAlignM();
     772             :     }
     773             : }
     774             : 
     775             : 
     776          45 : SmNode * SmTableNode::GetLeftMost()
     777             : {
     778          45 :     return this;
     779             : }
     780             : 
     781             : 
     782         561 : long SmTableNode::GetFormulaBaseline() const
     783             : {
     784         561 :     return nFormulaBaseline;
     785             : }
     786             : 
     787             : 
     788             : /**************************************************************************/
     789             : 
     790             : 
     791        2060 : void SmLineNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
     792             : {
     793        2060 :     SmNode::Prepare(rFormat, rDocShell);
     794             : 
     795             :     // Here we use the 'FNT_VARIABLE' font since it's ascent and descent in general fit better
     796             :     // to the rest of the formula compared to the 'FNT_MATH' font.
     797        2060 :     GetFont() = rFormat.GetFont(FNT_VARIABLE);
     798        2060 :     Flags() |= FLG_FONT;
     799        2060 : }
     800             : 
     801             : 
     802             : /**************************************************************************/
     803             : 
     804             : 
     805        1977 : void SmLineNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
     806             :     // arranges all subnodes in one row with some extra space between
     807             : {
     808             :     SmNode *pNode;
     809        1977 :     sal_uInt16  nSize = GetNumSubNodes();
     810             :     sal_uInt16 i;
     811        5210 :     for (i = 0; i < nSize;  i++)
     812        3233 :         if (NULL != (pNode = GetSubNode(i)))
     813        3233 :             pNode->Arrange(rDev, rFormat);
     814             : 
     815        1977 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
     816        1977 :     aTmpDev.SetFont(GetFont());
     817             : 
     818        1977 :     if (nSize < 1)
     819             :     {
     820             :         // provide an empty rectangle with alignment parameters for the "current"
     821             :         // font (in order to make "a^1 {}_2^3 a_4" work correct, that is, have the
     822             :         // same sub-/supscript positions.)
     823             :         //! be sure to use a character that has explicitly defined HiAttribut
     824             :         //! line in rect.cxx such as 'a' in order to make 'vec a' look same to
     825             :         //! 'vec {a}'.
     826             :         SmRect::operator = (SmRect(aTmpDev, &rFormat, OUString("a"),
     827         223 :                             GetFont().GetBorderWidth()));
     828             :         // make sure that the rectangle occupies (almost) no space
     829         223 :         SetWidth(1);
     830         223 :         SetItalicSpaces(0, 0);
     831        2200 :         return;
     832             :     }
     833             : 
     834             :     // make distance depend on font size
     835        1754 :     long nDist = (rFormat.GetDistance(DIS_HORIZONTAL) * GetFont().GetSize().Height()) / 100L;
     836        1754 :     if (!IsUseExtraSpaces())
     837           0 :         nDist = 0;
     838             : 
     839        1754 :     Point   aPos;
     840             :     // copy the first node into LineNode and extend by the others
     841        1754 :     if (NULL != (pNode = GetSubNode(0)))
     842        1754 :         SmRect::operator = (pNode->GetRect());
     843             : 
     844        3233 :     for (i = 1;  i < nSize;  i++)
     845        1479 :         if (NULL != (pNode = GetSubNode(i)))
     846             :         {
     847        1479 :             aPos = pNode->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
     848             : 
     849             :             // add horizontal space to the left for each but the first sub node
     850        1479 :             aPos.X() += nDist;
     851             : 
     852        1479 :             pNode->MoveTo(aPos);
     853        1479 :             ExtendBy( *pNode, RCP_XOR );
     854        1754 :         }
     855             : }
     856             : 
     857             : 
     858             : /**************************************************************************/
     859             : 
     860             : 
     861         894 : void SmExpressionNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
     862             :     // as 'SmLineNode::Arrange' but keeps alignment of leftmost subnode
     863             : {
     864         894 :     SmLineNode::Arrange(rDev, rFormat);
     865             : 
     866             :     //  copy alignment of leftmost subnode if any
     867         894 :     SmNode *pNode = GetLeftMost();
     868         894 :     if (pNode)
     869         894 :         SetRectHorAlign(pNode->GetRectHorAlign(), false);
     870         894 : }
     871             : 
     872             : 
     873             : /**************************************************************************/
     874             : 
     875             : 
     876         139 : void SmUnHorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
     877             : {
     878         139 :     bool  bIsPostfix = GetToken().eType == TFACT;
     879             : 
     880         139 :     SmNode *pOper = GetSubNode(bIsPostfix ? 1 : 0),
     881         139 :            *pBody = GetSubNode(bIsPostfix ? 0 : 1);
     882             :     OSL_ENSURE(pOper, "Sm: NULL pointer");
     883             :     OSL_ENSURE(pBody, "Sm: NULL pointer");
     884             : 
     885         139 :     pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100));
     886         139 :     pOper->Arrange(rDev, rFormat);
     887         139 :     pBody->Arrange(rDev, rFormat);
     888             : 
     889             :     Point  aPos = pOper->AlignTo(*pBody, bIsPostfix ? RP_RIGHT : RP_LEFT,
     890         139 :                         RHA_CENTER, RVA_BASELINE);
     891             :     // add a bit space between operator and argument
     892             :     // (worst case -{1 over 2} where - and over have almost no space inbetween)
     893         139 :     long  nDelta = pOper->GetFont().GetSize().Height() / 20;
     894         139 :     if (bIsPostfix)
     895           0 :         aPos.X() += nDelta;
     896             :     else
     897         139 :         aPos.X() -= nDelta;
     898         139 :     pOper->MoveTo(aPos);
     899             : 
     900         139 :     SmRect::operator = (*pBody);
     901         139 :     long  nOldBot = GetBottom();
     902             : 
     903         139 :     ExtendBy(*pOper, RCP_XOR);
     904             : 
     905             :     // workaround for Bug 50865: "a^2 a^+2" have different baselines
     906             :     // for exponents (if size of exponent is large enough)
     907         139 :     SetBottom(nOldBot);
     908         139 : }
     909             : 
     910             : 
     911             : /**************************************************************************/
     912             : 
     913             : 
     914          78 : void SmRootNode::GetHeightVerOffset(const SmRect &rRect,
     915             :                                     long &rHeight, long &rVerOffset)
     916             :     // calculate height and vertical offset of root sign suitable for 'rRect'
     917             : {
     918          78 :     rVerOffset = (rRect.GetBottom() - rRect.GetAlignB()) / 2;
     919          78 :     rHeight    = rRect.GetHeight() - rVerOffset;
     920             : 
     921             :     OSL_ENSURE(rHeight    >= 0, "Sm : Ooops...");
     922             :     OSL_ENSURE(rVerOffset >= 0, "Sm : Ooops...");
     923          78 : }
     924             : 
     925             : 
     926          15 : Point SmRootNode::GetExtraPos(const SmRect &rRootSymbol,
     927             :                               const SmRect &rExtra)
     928             : {
     929          15 :     const Size &rSymSize = rRootSymbol.GetSize();
     930             : 
     931          15 :     Point  aPos = rRootSymbol.GetTopLeft()
     932          15 :             + Point((rSymSize.Width()  * 70) / 100,
     933          45 :                     (rSymSize.Height() * 52) / 100);
     934             : 
     935             :     // from this calculate topleft edge of 'rExtra'
     936          15 :     aPos.X() -= rExtra.GetWidth() + rExtra.GetItalicRightSpace();
     937          15 :     aPos.Y() -= rExtra.GetHeight();
     938             :     // if there's enough space move a bit less to the right
     939             :     // examples: "nroot i a", "nroot j a"
     940             :     // (it looks better if we don't use italic-spaces here)
     941          15 :     long  nX = rRootSymbol.GetLeft() + (rSymSize.Width() * 30) / 100;
     942          15 :     if (aPos.X() > nX)
     943           0 :         aPos.X() = nX;
     944             : 
     945          15 :     return aPos;
     946             : }
     947             : 
     948             : 
     949          78 : void SmRootNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
     950             : {
     951             :     //! pExtra needs to have the smaller index than pRootSym in order to
     952             :     //! not to get the root symbol but the pExtra when clicking on it in the
     953             :     //! GraphicWindow. (That is because of the simplicity of the algorithm
     954             :     //! that finds the node corresponding to a mouseclick in the window.)
     955          78 :     SmNode *pExtra   = GetSubNode(0),
     956          78 :            *pRootSym = GetSubNode(1),
     957          78 :            *pBody    = GetSubNode(2);
     958             :     OSL_ENSURE(pRootSym, "Sm: NULL pointer");
     959             :     OSL_ENSURE(pBody,    "Sm: NULL pointer");
     960             : 
     961          78 :     pBody->Arrange(rDev, rFormat);
     962             : 
     963             :     long  nHeight,
     964             :           nVerOffset;
     965          78 :     GetHeightVerOffset(*pBody, nHeight, nVerOffset);
     966          78 :     nHeight += rFormat.GetDistance(DIS_ROOT)
     967          78 :                * GetFont().GetSize().Height() / 100L;
     968             : 
     969             :     // font specialist advised to change the width first
     970          78 :     pRootSym->AdaptToY(rDev, nHeight);
     971          78 :     pRootSym->AdaptToX(rDev, pBody->GetItalicWidth());
     972             : 
     973          78 :     pRootSym->Arrange(rDev, rFormat);
     974             : 
     975          78 :     Point  aPos = pRootSym->AlignTo(*pBody, RP_LEFT, RHA_CENTER, RVA_BASELINE);
     976             :     //! override calculated vertical position
     977          78 :     aPos.Y()  = pRootSym->GetTop() + pBody->GetBottom() - pRootSym->GetBottom();
     978          78 :     aPos.Y() -= nVerOffset;
     979          78 :     pRootSym->MoveTo(aPos);
     980             : 
     981          78 :     if (pExtra)
     982          15 :     {   pExtra->SetSize(Fraction(rFormat.GetRelSize(SIZ_INDEX), 100));
     983          15 :         pExtra->Arrange(rDev, rFormat);
     984             : 
     985          15 :         aPos = GetExtraPos(*pRootSym, *pExtra);
     986          15 :         pExtra->MoveTo(aPos);
     987             :     }
     988             : 
     989          78 :     SmRect::operator = (*pBody);
     990          78 :     ExtendBy(*pRootSym, RCP_THIS);
     991          78 :     if (pExtra)
     992          15 :         ExtendBy(*pExtra, RCP_THIS, true);
     993          78 : }
     994             : 
     995             : 
     996           0 : void SmRootNode::CreateTextFromNode(OUString &rText)
     997             : {
     998           0 :     SmNode *pExtra = GetSubNode(0);
     999           0 :     if (pExtra)
    1000             :     {
    1001           0 :         rText += "nroot ";
    1002           0 :         pExtra->CreateTextFromNode(rText);
    1003             :     }
    1004             :     else
    1005           0 :         rText += "sqrt ";
    1006             : 
    1007           0 :     if (!pExtra && GetSubNode(2)->GetNumSubNodes() > 1)
    1008           0 :         rText += "{ ";
    1009             : 
    1010           0 :     GetSubNode(2)->CreateTextFromNode(rText);
    1011             : 
    1012           0 :     if (!pExtra && GetSubNode(2)->GetNumSubNodes() > 1)
    1013           0 :         rText += "} ";
    1014           0 : }
    1015             : 
    1016             : /**************************************************************************/
    1017             : 
    1018             : 
    1019           0 : void SmDynIntegralNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1020             : {
    1021           0 :     SmNode  *pDynIntegralSym = Symbol(),
    1022           0 :            *pBody    = Body();
    1023             :     OSL_ENSURE(pDynIntegralSym, "Sm: NULL pointer");
    1024             :     OSL_ENSURE(pBody,    "Sm: NULL pointer");
    1025             : 
    1026           0 :     pBody->Arrange(rDev, rFormat);
    1027             : 
    1028           0 :     long  nHeight = pBody->GetHeight();
    1029           0 :     pDynIntegralSym->AdaptToY(rDev, nHeight);
    1030             : 
    1031           0 :     pDynIntegralSym->Arrange(rDev, rFormat);
    1032             : 
    1033           0 :     Point  aPos = pDynIntegralSym->AlignTo(*pBody, RP_LEFT, RHA_CENTER, RVA_BASELINE);
    1034             :     //! override calculated vertical position
    1035           0 :     aPos.Y()  = pDynIntegralSym->GetTop() + pBody->GetBottom() - pDynIntegralSym->GetBottom();
    1036           0 :     pDynIntegralSym->MoveTo(aPos);
    1037             : 
    1038             : 
    1039             :     // override its own rectangle with pBody's
    1040           0 :     SmRect::operator = (*pBody);
    1041             :     // extends this rectangle with the symbol's one
    1042           0 :     ExtendBy(*pDynIntegralSym, RCP_THIS);
    1043             : 
    1044           0 : }
    1045             : 
    1046             : 
    1047           0 : void SmDynIntegralNode::CreateTextFromNode(OUString &rText)
    1048             : {
    1049             : 
    1050           0 :     rText += "intd ";
    1051           0 :     SmNode *pBody = GetSubNode(1);
    1052             : 
    1053           0 :     if (pBody->GetNumSubNodes() > 1)
    1054           0 :         rText += "{ ";
    1055             : 
    1056           0 :     pBody->CreateTextFromNode(rText);
    1057             : 
    1058           0 :     if (pBody->GetNumSubNodes() > 1)
    1059           0 :         rText += "} ";
    1060           0 : }
    1061             : 
    1062             : 
    1063             : 
    1064             : /**************************************************************************/
    1065             : 
    1066             : 
    1067         826 : void SmBinHorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1068             : {
    1069         826 :     SmNode *pLeft  = GetSubNode(0),
    1070         826 :            *pOper  = GetSubNode(1),
    1071         826 :            *pRight = GetSubNode(2);
    1072             :     OSL_ENSURE(pLeft  != NULL, "Sm: NULL pointer");
    1073             :     OSL_ENSURE(pOper  != NULL, "Sm: NULL pointer");
    1074             :     OSL_ENSURE(pRight != NULL, "Sm: NULL pointer");
    1075             : 
    1076         826 :     pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100));
    1077             : 
    1078         826 :     pLeft ->Arrange(rDev, rFormat);
    1079         826 :     pOper ->Arrange(rDev, rFormat);
    1080         826 :     pRight->Arrange(rDev, rFormat);
    1081             : 
    1082         826 :     const SmRect &rOpRect = pOper->GetRect();
    1083             : 
    1084        1652 :     long nDist = (rOpRect.GetWidth() *
    1085        1652 :                  rFormat.GetDistance(DIS_HORIZONTAL)) / 100L;
    1086             : 
    1087         826 :     SmRect::operator = (*pLeft);
    1088             : 
    1089         826 :     Point aPos;
    1090         826 :     aPos = pOper->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
    1091         826 :     aPos.X() += nDist;
    1092         826 :     pOper->MoveTo(aPos);
    1093         826 :     ExtendBy(*pOper, RCP_XOR);
    1094             : 
    1095         826 :     aPos = pRight->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
    1096         826 :     aPos.X() += nDist;
    1097             : 
    1098         826 :     pRight->MoveTo(aPos);
    1099         826 :     ExtendBy(*pRight, RCP_XOR);
    1100         826 : }
    1101             : 
    1102             : 
    1103             : /**************************************************************************/
    1104             : 
    1105             : 
    1106         239 : void SmBinVerNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1107             : {
    1108         239 :     SmNode *pNum   = GetSubNode(0),
    1109         239 :            *pLine  = GetSubNode(1),
    1110         239 :            *pDenom = GetSubNode(2);
    1111             :     OSL_ENSURE(pNum,   "Sm : NULL pointer");
    1112             :     OSL_ENSURE(pLine,  "Sm : NULL pointer");
    1113             :     OSL_ENSURE(pDenom, "Sm : NULL pointer");
    1114             : 
    1115         239 :     bool  bIsTextmode = rFormat.IsTextmode();
    1116         239 :     if (bIsTextmode)
    1117             :     {
    1118           0 :         Fraction  aFraction(rFormat.GetRelSize(SIZ_INDEX), 100);
    1119           0 :         pNum  ->SetSize(aFraction);
    1120           0 :         pLine ->SetSize(aFraction);
    1121           0 :         pDenom->SetSize(aFraction);
    1122             :     }
    1123             : 
    1124         239 :     pNum  ->Arrange(rDev, rFormat);
    1125         239 :     pDenom->Arrange(rDev, rFormat);
    1126             : 
    1127         239 :     long  nFontHeight = GetFont().GetSize().Height(),
    1128         239 :           nExtLen     = nFontHeight * rFormat.GetDistance(DIS_FRACTION) / 100L,
    1129         239 :           nThick      = nFontHeight * rFormat.GetDistance(DIS_STROKEWIDTH) / 100L,
    1130         239 :           nWidth      = std::max(pNum->GetItalicWidth(), pDenom->GetItalicWidth()),
    1131             :           nNumDist    = bIsTextmode ? 0 :
    1132         239 :                             nFontHeight * rFormat.GetDistance(DIS_NUMERATOR)   / 100L,
    1133             :           nDenomDist  = bIsTextmode ? 0 :
    1134         239 :                             nFontHeight * rFormat.GetDistance(DIS_DENOMINATOR) / 100L;
    1135             : 
    1136             :     // font specialist advised to change the width first
    1137         239 :     pLine->AdaptToY(rDev, nThick);
    1138         239 :     pLine->AdaptToX(rDev, nWidth + 2 * nExtLen);
    1139         239 :     pLine->Arrange(rDev, rFormat);
    1140             : 
    1141             :     // get horizontal alignment for numerator
    1142         239 :     const SmNode *pLM       = pNum->GetLeftMost();
    1143         239 :     RectHorAlign  eHorAlign = pLM->GetRectHorAlign();
    1144             : 
    1145             :     // move numerator to its position
    1146         239 :     Point  aPos = pNum->AlignTo(*pLine, RP_TOP, eHorAlign, RVA_BASELINE);
    1147         239 :     aPos.Y() -= nNumDist;
    1148         239 :     pNum->MoveTo(aPos);
    1149             : 
    1150             :     // get horizontal alignment for denominator
    1151         239 :     pLM       = pDenom->GetLeftMost();
    1152         239 :     eHorAlign = pLM->GetRectHorAlign();
    1153             : 
    1154             :     // move denominator to its position
    1155         239 :     aPos = pDenom->AlignTo(*pLine, RP_BOTTOM, eHorAlign, RVA_BASELINE);
    1156         239 :     aPos.Y() += nDenomDist;
    1157         239 :     pDenom->MoveTo(aPos);
    1158             : 
    1159         239 :     SmRect::operator = (*pNum);
    1160         239 :     ExtendBy(*pDenom, RCP_NONE).ExtendBy(*pLine, RCP_NONE, pLine->GetCenterY());
    1161         239 : }
    1162             : 
    1163           0 : void SmBinVerNode::CreateTextFromNode(OUString &rText)
    1164             : {
    1165           0 :     SmNode *pNum   = GetSubNode(0),
    1166           0 :            *pDenom = GetSubNode(2);
    1167           0 :     pNum->CreateTextFromNode(rText);
    1168           0 :     rText += "over ";
    1169           0 :     pDenom->CreateTextFromNode(rText);
    1170           0 : }
    1171             : 
    1172             : 
    1173          42 : SmNode * SmBinVerNode::GetLeftMost()
    1174             : {
    1175          42 :     return this;
    1176             : }
    1177             : 
    1178             : 
    1179             : namespace {
    1180             : 
    1181             : /// @return value of the determinant formed by the two points
    1182          68 : double Det(const Point &rHeading1, const Point &rHeading2)
    1183             : {
    1184          68 :     return rHeading1.X() * rHeading2.Y() - rHeading1.Y() * rHeading2.X();
    1185             : }
    1186             : 
    1187             : 
    1188             : /// Is true iff the point 'rPoint1' belongs to the straight line through 'rPoint2'
    1189             : /// and has the direction vector 'rHeading2'
    1190           0 : bool IsPointInLine(const Point &rPoint1,
    1191             :                    const Point &rPoint2, const Point &rHeading2)
    1192             : {
    1193             :     OSL_ENSURE(rHeading2 != Point(), "Sm : 0 vector");
    1194             : 
    1195           0 :     bool bRes = false;
    1196             :     static const double eps = 5.0 * DBL_EPSILON;
    1197             : 
    1198             :     double fLambda;
    1199           0 :     if (labs(rHeading2.X()) > labs(rHeading2.Y()))
    1200             :     {
    1201           0 :         fLambda = (rPoint1.X() - rPoint2.X()) / (double) rHeading2.X();
    1202           0 :         bRes = fabs(rPoint1.Y() - (rPoint2.Y() + fLambda * rHeading2.Y())) < eps;
    1203             :     }
    1204             :     else
    1205             :     {
    1206           0 :         fLambda = (rPoint1.Y() - rPoint2.Y()) / (double) rHeading2.Y();
    1207           0 :         bRes = fabs(rPoint1.X() - (rPoint2.X() + fLambda * rHeading2.X())) < eps;
    1208             :     }
    1209             : 
    1210           0 :     return bRes;
    1211             : }
    1212             : 
    1213             : 
    1214          68 : sal_uInt16 GetLineIntersectionPoint(Point &rResult,
    1215             :                                 const Point& rPoint1, const Point &rHeading1,
    1216             :                                 const Point& rPoint2, const Point &rHeading2)
    1217             : {
    1218             :     OSL_ENSURE(rHeading1 != Point(), "Sm : 0 vector");
    1219             :     OSL_ENSURE(rHeading2 != Point(), "Sm : 0 vector");
    1220             : 
    1221          68 :     sal_uInt16 nRes = 1;
    1222             :     static const double eps = 5.0 * DBL_EPSILON;
    1223             : 
    1224             :     // are the direction vectors linearly dependent?
    1225          68 :     double  fDet = Det(rHeading1, rHeading2);
    1226          68 :     if (fabs(fDet) < eps)
    1227             :     {
    1228           0 :         nRes    = IsPointInLine(rPoint1, rPoint2, rHeading2) ? USHRT_MAX : 0;
    1229           0 :         rResult = nRes ? rPoint1 : Point();
    1230             :     }
    1231             :     else
    1232             :     {
    1233             :         // here we do not pay attention to the computational accurancy
    1234             :         // (that would be more complicated and is not really worth it in this case)
    1235          68 :         double fLambda = (    (rPoint1.Y() - rPoint2.Y()) * rHeading2.X()
    1236          68 :                             - (rPoint1.X() - rPoint2.X()) * rHeading2.Y())
    1237          68 :                          / fDet;
    1238          68 :         rResult = Point(rPoint1.X() + (long) (fLambda * rHeading1.X()),
    1239         136 :                         rPoint1.Y() + (long) (fLambda * rHeading1.Y()));
    1240             :     }
    1241             : 
    1242          68 :     return nRes;
    1243             : }
    1244             : 
    1245             : }
    1246             : 
    1247             : 
    1248          34 : SmBinDiagonalNode::SmBinDiagonalNode(const SmToken &rNodeToken)
    1249          34 : :   SmStructureNode(NBINDIAGONAL, rNodeToken)
    1250             : {
    1251          34 :     bAscending = false;
    1252          34 :     SetNumSubNodes(3);
    1253          34 : }
    1254             : 
    1255             : 
    1256             : /// @return position and size of the diagonal line
    1257             : /// premise: SmRect of the node defines the limitation(!) consequently it has to be known upfront
    1258          34 : void SmBinDiagonalNode::GetOperPosSize(Point &rPos, Size &rSize,
    1259             :                         const Point &rDiagPoint, double fAngleDeg) const
    1260             : 
    1261             : {
    1262             :     static const double  fPi   = 3.1415926535897932384626433;
    1263          34 :     double  fAngleRad   = fAngleDeg / 180.0 * fPi;
    1264          34 :     long    nRectLeft   = GetItalicLeft(),
    1265          34 :             nRectRight  = GetItalicRight(),
    1266          34 :             nRectTop    = GetTop(),
    1267          34 :             nRectBottom = GetBottom();
    1268          34 :     Point   aRightHdg     (100, 0),
    1269          34 :             aDownHdg      (0, 100),
    1270          34 :             aDiagHdg      ( (long)(100.0 * cos(fAngleRad)),
    1271          68 :                             (long)(-100.0 * sin(fAngleRad)) );
    1272             : 
    1273             :     long  nLeft, nRight, nTop, nBottom;     // margins of the rectangle for the diagonal
    1274          34 :     Point aPoint;
    1275          34 :     if (IsAscending())
    1276             :     {
    1277             :         // determine top right corner
    1278             :         GetLineIntersectionPoint(aPoint,
    1279             :             Point(nRectLeft, nRectTop), aRightHdg,
    1280          17 :             rDiagPoint, aDiagHdg);
    1281             :         // is there a point of intersection with the top border?
    1282          17 :         if (aPoint.X() <= nRectRight)
    1283             :         {
    1284          17 :             nRight = aPoint.X();
    1285          17 :             nTop   = nRectTop;
    1286             :         }
    1287             :         else
    1288             :         {
    1289             :             // there has to be a point of intersection with the right border!
    1290             :             GetLineIntersectionPoint(aPoint,
    1291             :                 Point(nRectRight, nRectTop), aDownHdg,
    1292           0 :                 rDiagPoint, aDiagHdg);
    1293             : 
    1294           0 :             nRight = nRectRight;
    1295           0 :             nTop   = aPoint.Y();
    1296             :         }
    1297             : 
    1298             :         // determine bottom left corner
    1299             :         GetLineIntersectionPoint(aPoint,
    1300             :             Point(nRectLeft, nRectBottom), aRightHdg,
    1301          17 :             rDiagPoint, aDiagHdg);
    1302             :         // is there a point of intersection with the bottom border?
    1303          17 :         if (aPoint.X() >= nRectLeft)
    1304             :         {
    1305          17 :             nLeft   = aPoint.X();
    1306          17 :             nBottom = nRectBottom;
    1307             :         }
    1308             :         else
    1309             :         {
    1310             :             // there has to be a point of intersection with the left border!
    1311             :             GetLineIntersectionPoint(aPoint,
    1312             :                 Point(nRectLeft, nRectTop), aDownHdg,
    1313           0 :                 rDiagPoint, aDiagHdg);
    1314             : 
    1315           0 :             nLeft   = nRectLeft;
    1316           0 :             nBottom = aPoint.Y();
    1317             :         }
    1318             :     }
    1319             :     else
    1320             :     {
    1321             :         // determine top left corner
    1322             :         GetLineIntersectionPoint(aPoint,
    1323             :             Point(nRectLeft, nRectTop), aRightHdg,
    1324          17 :             rDiagPoint, aDiagHdg);
    1325             :         // is there a point of intersection with the top border?
    1326          17 :         if (aPoint.X() >= nRectLeft)
    1327             :         {
    1328          17 :             nLeft = aPoint.X();
    1329          17 :             nTop  = nRectTop;
    1330             :         }
    1331             :         else
    1332             :         {
    1333             :             // there has to be a point of intersection with the left border!
    1334             :             GetLineIntersectionPoint(aPoint,
    1335             :                 Point(nRectLeft, nRectTop), aDownHdg,
    1336           0 :                 rDiagPoint, aDiagHdg);
    1337             : 
    1338           0 :             nLeft = nRectLeft;
    1339           0 :             nTop  = aPoint.Y();
    1340             :         }
    1341             : 
    1342             :         // determine bottom right corner
    1343             :         GetLineIntersectionPoint(aPoint,
    1344             :             Point(nRectLeft, nRectBottom), aRightHdg,
    1345          17 :             rDiagPoint, aDiagHdg);
    1346             :         // is there a point of intersection with the bottom border?
    1347          17 :         if (aPoint.X() <= nRectRight)
    1348             :         {
    1349          17 :             nRight  = aPoint.X();
    1350          17 :             nBottom = nRectBottom;
    1351             :         }
    1352             :         else
    1353             :         {
    1354             :             // there has to be a point of intersection with the right border!
    1355             :             GetLineIntersectionPoint(aPoint,
    1356             :                 Point(nRectRight, nRectTop), aDownHdg,
    1357           0 :                 rDiagPoint, aDiagHdg);
    1358             : 
    1359           0 :             nRight  = nRectRight;
    1360           0 :             nBottom = aPoint.Y();
    1361             :         }
    1362             :     }
    1363             : 
    1364          34 :     rSize = Size(nRight - nLeft + 1, nBottom - nTop + 1);
    1365          34 :     rPos.X() = nLeft;
    1366          34 :     rPos.Y() = nTop;
    1367          34 : }
    1368             : 
    1369             : 
    1370          34 : void SmBinDiagonalNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1371             : {
    1372             :     // Both arguments have to get into the SubNodes before the Operator so that clicking
    1373             :     // within the GraphicWindow sets the FormulaCursor correctly (cf. SmRootNode)
    1374          34 :     SmNode *pLeft  = GetSubNode(0),
    1375          34 :            *pRight = GetSubNode(1);
    1376             :     OSL_ENSURE(pLeft, "Sm : NULL pointer");
    1377             :     OSL_ENSURE(pRight, "Sm : NULL pointer");
    1378             : 
    1379             :     OSL_ENSURE(GetSubNode(2)->GetType() == NPOLYLINE, "Sm : wrong node type");
    1380          34 :     SmPolyLineNode *pOper = static_cast<SmPolyLineNode *>(GetSubNode(2));
    1381             :     OSL_ENSURE(pOper, "Sm : NULL pointer");
    1382             : 
    1383             :     //! some routines being called extract some info from the OutputDevice's
    1384             :     //! font (eg the space to be used for borders OR the font name(!!)).
    1385             :     //! Thus the font should reflect the needs and has to be set!
    1386          34 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    1387          34 :     aTmpDev.SetFont(GetFont());
    1388             : 
    1389          34 :     pLeft->Arrange(aTmpDev, rFormat);
    1390          34 :     pRight->Arrange(aTmpDev, rFormat);
    1391             : 
    1392             :     // determine implicitly the values (incl. the margin) of the diagonal line
    1393          34 :     pOper->Arrange(aTmpDev, rFormat);
    1394             : 
    1395          34 :     long nDelta = pOper->GetWidth() * 8 / 10;
    1396             : 
    1397             :     // determine TopLeft position from the right argument
    1398          34 :     Point aPos;
    1399          34 :     aPos.X() = pLeft->GetItalicRight() + nDelta + pRight->GetItalicLeftSpace();
    1400          34 :     if (IsAscending())
    1401          17 :         aPos.Y() = pLeft->GetBottom() + nDelta;
    1402             :     else
    1403          17 :         aPos.Y() = pLeft->GetTop() - nDelta - pRight->GetHeight();
    1404             : 
    1405          34 :     pRight->MoveTo(aPos);
    1406             : 
    1407             :     // determine new baseline
    1408          51 :     long nTmpBaseline = IsAscending() ? (pLeft->GetBottom() + pRight->GetTop()) / 2
    1409          51 :                         : (pLeft->GetTop() + pRight->GetBottom()) / 2;
    1410          34 :     Point  aLogCenter ((pLeft->GetItalicRight() + pRight->GetItalicLeft()) / 2,
    1411          34 :                        nTmpBaseline);
    1412             : 
    1413          34 :     SmRect::operator = (*pLeft);
    1414          34 :     ExtendBy(*pRight, RCP_NONE);
    1415             : 
    1416             : 
    1417             :     // determine position and size of diagonal line
    1418          34 :     Size  aTmpSize;
    1419          34 :     GetOperPosSize(aPos, aTmpSize, aLogCenter, IsAscending() ? 60.0 : -60.0);
    1420             : 
    1421             :     // font specialist advised to change the width first
    1422          34 :     pOper->AdaptToY(aTmpDev, aTmpSize.Height());
    1423          34 :     pOper->AdaptToX(aTmpDev, aTmpSize.Width());
    1424             :     // and make it active
    1425          34 :     pOper->Arrange(aTmpDev, rFormat);
    1426             : 
    1427          34 :     pOper->MoveTo(aPos);
    1428             : 
    1429          34 :     ExtendBy(*pOper, RCP_NONE, nTmpBaseline);
    1430          34 : }
    1431             : 
    1432             : 
    1433             : /**************************************************************************/
    1434             : 
    1435             : 
    1436         744 : void SmSubSupNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1437             : {
    1438             :     OSL_ENSURE(GetNumSubNodes() == 1 + SUBSUP_NUM_ENTRIES,
    1439             :                "Sm: wrong number of subnodes");
    1440             : 
    1441         744 :     SmNode *pBody = GetBody();
    1442             :     OSL_ENSURE(pBody, "Sm: NULL pointer");
    1443             : 
    1444         744 :     long  nOrigHeight = pBody->GetFont().GetSize().Height();
    1445             : 
    1446         744 :     pBody->Arrange(rDev, rFormat);
    1447             : 
    1448         744 :     const SmRect &rBodyRect = pBody->GetRect();
    1449         744 :     SmRect::operator = (rBodyRect);
    1450             : 
    1451             :     // line that separates sub- and supscript rectangles
    1452         744 :     long  nDelimLine = SmFromTo(GetAlignB(), GetAlignT(), 0.4);
    1453             : 
    1454         744 :     Point  aPos;
    1455             :     long   nDelta, nDist;
    1456             : 
    1457             :     // iterate over all possible sub-/supscripts
    1458         744 :     SmRect  aTmpRect (rBodyRect);
    1459        5208 :     for (int i = 0;  i < SUBSUP_NUM_ENTRIES;  i++)
    1460        4464 :     {   SmSubSup  eSubSup = (SmSubSup) i;   // cast
    1461        4464 :         SmNode *pSubSup = GetSubSup(eSubSup);
    1462             : 
    1463        4464 :         if (!pSubSup)
    1464        3472 :             continue;
    1465             : 
    1466             :         // switch position of limits if we are in textmode
    1467         992 :         if (rFormat.IsTextmode()  &&  (GetToken().nGroup & TGLIMIT))
    1468           0 :             switch (eSubSup)
    1469           0 :             {   case CSUB:  eSubSup = RSUB;     break;
    1470           0 :                 case CSUP:  eSubSup = RSUP;     break;
    1471             :                 default:
    1472           0 :                     break;
    1473             :             }
    1474             : 
    1475             :         // prevent sub-/supscripts from diminishing in size
    1476             :         // (as would be in "a_{1_{2_{3_4}}}")
    1477         992 :         if (GetFont().GetSize().Height() > rFormat.GetBaseSize().Height() / 3)
    1478             :         {
    1479         830 :             sal_uInt16 nIndex = (eSubSup == CSUB  ||  eSubSup == CSUP) ?
    1480        1301 :                                     SIZ_LIMITS : SIZ_INDEX;
    1481         992 :             Fraction  aFraction ( rFormat.GetRelSize(nIndex), 100 );
    1482         992 :             pSubSup->SetSize(aFraction);
    1483             :         }
    1484             : 
    1485         992 :         pSubSup->Arrange(rDev, rFormat);
    1486             : 
    1487         992 :         bool  bIsTextmode = rFormat.IsTextmode();
    1488         992 :         nDist = 0;
    1489             : 
    1490             :         //! be sure that CSUB, CSUP are handled before the other cases!
    1491         992 :         switch (eSubSup)
    1492             :         {   case RSUB :
    1493             :             case LSUB :
    1494         236 :                 if (!bIsTextmode)
    1495             :                     nDist = nOrigHeight
    1496         236 :                             * rFormat.GetDistance(DIS_SUBSCRIPT) / 100L;
    1497         236 :                 aPos  = pSubSup->GetRect().AlignTo(aTmpRect,
    1498             :                                 eSubSup == LSUB ? RP_LEFT : RP_RIGHT,
    1499         472 :                                 RHA_CENTER, RVA_BOTTOM);
    1500         236 :                 aPos.Y() += nDist;
    1501         236 :                 nDelta = nDelimLine - aPos.Y();
    1502         236 :                 if (nDelta > 0)
    1503         236 :                     aPos.Y() += nDelta;
    1504         236 :                 break;
    1505             :             case RSUP :
    1506             :             case LSUP :
    1507         447 :                 if (!bIsTextmode)
    1508             :                     nDist = nOrigHeight
    1509         447 :                             * rFormat.GetDistance(DIS_SUPERSCRIPT) / 100L;
    1510         447 :                 aPos  = pSubSup->GetRect().AlignTo(aTmpRect,
    1511             :                                 eSubSup == LSUP ? RP_LEFT : RP_RIGHT,
    1512         894 :                                 RHA_CENTER, RVA_TOP);
    1513         447 :                 aPos.Y() -= nDist;
    1514         447 :                 nDelta = aPos.Y() + pSubSup->GetHeight() - nDelimLine;
    1515         447 :                 if (nDelta > 0)
    1516           9 :                     aPos.Y() -= nDelta;
    1517         447 :                 break;
    1518             :             case CSUB :
    1519         162 :                 if (!bIsTextmode)
    1520             :                     nDist = nOrigHeight
    1521         162 :                             * rFormat.GetDistance(DIS_LOWERLIMIT) / 100L;
    1522         162 :                 aPos = pSubSup->GetRect().AlignTo(rBodyRect, RP_BOTTOM,
    1523         162 :                                 RHA_CENTER, RVA_BASELINE);
    1524         162 :                 aPos.Y() += nDist;
    1525         162 :                 break;
    1526             :             case CSUP :
    1527         147 :                 if (!bIsTextmode)
    1528             :                     nDist = nOrigHeight
    1529         147 :                             * rFormat.GetDistance(DIS_UPPERLIMIT) / 100L;
    1530         147 :                 aPos = pSubSup->GetRect().AlignTo(rBodyRect, RP_TOP,
    1531         147 :                                 RHA_CENTER, RVA_BASELINE);
    1532         147 :                 aPos.Y() -= nDist;
    1533         147 :                 break;
    1534             :         }
    1535             : 
    1536         992 :         pSubSup->MoveTo(aPos);
    1537         992 :         ExtendBy(*pSubSup, RCP_THIS, true);
    1538             : 
    1539             :         // update rectangle to which  RSUB, RSUP, LSUB, LSUP
    1540             :         // will be aligned to
    1541         992 :         if (eSubSup == CSUB  ||  eSubSup == CSUP)
    1542         309 :             aTmpRect = *this;
    1543             :     }
    1544         744 : }
    1545             : 
    1546           2 : void SmSubSupNode::CreateTextFromNode(OUString &rText)
    1547             : {
    1548             :     SmNode *pNode;
    1549           2 :     GetSubNode(0)->CreateTextFromNode(rText);
    1550             : 
    1551           2 :     if (NULL != (pNode = GetSubNode(LSUB+1)))
    1552             :     {
    1553           0 :         rText += "lsub ";
    1554           0 :         pNode->CreateTextFromNode(rText);
    1555             :     }
    1556           2 :     if (NULL != (pNode = GetSubNode(LSUP+1)))
    1557             :     {
    1558           0 :         rText += "lsup ";
    1559           0 :         pNode->CreateTextFromNode(rText);
    1560             :     }
    1561           2 :     if (NULL != (pNode = GetSubNode(CSUB+1)))
    1562             :     {
    1563           0 :         rText += "csub ";
    1564           0 :         pNode->CreateTextFromNode(rText);
    1565             :     }
    1566           2 :     if (NULL != (pNode = GetSubNode(CSUP+1)))
    1567             :     {
    1568           0 :         rText += "csup ";
    1569           0 :         pNode->CreateTextFromNode(rText);
    1570             :     }
    1571           2 :     if (NULL != (pNode = GetSubNode(RSUB+1)))
    1572             :     {
    1573           0 :         rText = comphelper::string::stripEnd(rText, ' ');
    1574           0 :         rText += "_";
    1575           0 :         pNode->CreateTextFromNode(rText);
    1576             :     }
    1577           2 :     if (NULL != (pNode = GetSubNode(RSUP+1)))
    1578             :     {
    1579           2 :         rText = comphelper::string::stripEnd(rText, ' ');
    1580           2 :         rText += "^";
    1581           2 :         pNode->CreateTextFromNode(rText);
    1582             :     }
    1583           2 : }
    1584             : 
    1585             : 
    1586             : /**************************************************************************/
    1587             : 
    1588           2 : void SmBraceNode::CreateTextFromNode(OUString &rText)
    1589             : {
    1590           2 :     if (GetScaleMode() == SCALE_HEIGHT)
    1591           2 :         rText += "left ";
    1592             :     {
    1593           2 :         OUString aStr;
    1594           2 :         GetSubNode(0)->CreateTextFromNode(aStr);
    1595           2 :         aStr = comphelper::string::strip(aStr, ' ');
    1596           2 :         aStr = comphelper::string::stripStart(aStr, '\\');
    1597           2 :         if (!aStr.isEmpty())
    1598             :         {
    1599           2 :             if (aStr == "divides")
    1600           0 :                 rText += "lline";
    1601           2 :             else if (aStr == "parallel")
    1602           0 :                 rText += "ldline";
    1603           2 :             else if (aStr == "<")
    1604           0 :                 rText += "langle";
    1605             :             else
    1606           2 :                 rText += aStr;
    1607           2 :             rText += " ";
    1608             :         }
    1609             :         else
    1610           0 :             rText += "none ";
    1611             :     }
    1612           2 :     GetSubNode(1)->CreateTextFromNode(rText);
    1613           2 :     if (GetScaleMode() == SCALE_HEIGHT)
    1614           2 :         rText += "right ";
    1615             :     {
    1616           2 :         OUString aStr;
    1617           2 :         GetSubNode(2)->CreateTextFromNode(aStr);
    1618           2 :         aStr = comphelper::string::strip(aStr, ' ');
    1619           2 :         aStr = comphelper::string::stripStart(aStr, '\\');
    1620           2 :         if (!aStr.isEmpty())
    1621             :         {
    1622           2 :             if (aStr == "divides")
    1623           0 :                 rText += "rline";
    1624           2 :             else if (aStr == "parallel")
    1625           0 :                 rText += "rdline";
    1626           2 :             else if (aStr == ">")
    1627           0 :                 rText += "rangle";
    1628             :             else
    1629           2 :                 rText += aStr;
    1630           2 :             rText += " ";
    1631             :         }
    1632             :         else
    1633           0 :             rText += "none ";
    1634             :     }
    1635           2 :     rText += " ";
    1636             : 
    1637           2 : }
    1638             : 
    1639         442 : void SmBraceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1640             : {
    1641         442 :     SmNode *pLeft  = GetSubNode(0),
    1642         442 :            *pBody  = GetSubNode(1),
    1643         442 :            *pRight = GetSubNode(2);
    1644             :     OSL_ENSURE(pLeft,  "Sm: NULL pointer");
    1645             :     OSL_ENSURE(pBody,  "Sm: NULL pointer");
    1646             :     OSL_ENSURE(pRight, "Sm: NULL pointer");
    1647             : 
    1648         442 :     pBody->Arrange(rDev, rFormat);
    1649             : 
    1650         442 :     bool  bIsScaleNormal = rFormat.IsScaleNormalBrackets(),
    1651        1260 :           bScale         = pBody->GetHeight() > 0  &&
    1652         851 :                            (GetScaleMode() == SCALE_HEIGHT  ||  bIsScaleNormal),
    1653         442 :           bIsABS         = GetToken().eType == TABS;
    1654             : 
    1655         442 :     long  nFaceHeight = GetFont().GetSize().Height();
    1656             : 
    1657             :     // determine oversize in %
    1658         442 :     sal_uInt16  nPerc = 0;
    1659         442 :     if (!bIsABS && bScale)
    1660             :     {   // in case of oversize braces...
    1661         409 :         sal_uInt16 nIndex = GetScaleMode() == SCALE_HEIGHT ?
    1662         409 :                             DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE;
    1663         409 :         nPerc = rFormat.GetDistance(nIndex);
    1664             :     }
    1665             : 
    1666             :     // determine the height for the braces
    1667             :     long  nBraceHeight;
    1668         442 :     if (bScale)
    1669             :     {
    1670         409 :         nBraceHeight = pBody->GetType() == NBRACEBODY ?
    1671             :                               static_cast<SmBracebodyNode *>(pBody)->GetBodyHeight()
    1672         409 :                             : pBody->GetHeight();
    1673         409 :         nBraceHeight += 2 * (nBraceHeight * nPerc / 100L);
    1674             :     }
    1675             :     else
    1676          33 :         nBraceHeight = nFaceHeight;
    1677             : 
    1678             :     // distance to the argument
    1679         442 :     nPerc = bIsABS ? 0 : rFormat.GetDistance(DIS_BRACKETSPACE);
    1680         442 :     long  nDist = nFaceHeight * nPerc / 100L;
    1681             : 
    1682             :     // if wanted, scale the braces to the wanted size
    1683         442 :     if (bScale)
    1684             :     {
    1685         409 :         Size  aTmpSize (pLeft->GetFont().GetSize());
    1686             :         OSL_ENSURE(pRight->GetFont().GetSize() == aTmpSize,
    1687             :                     "Sm : different font sizes");
    1688         818 :         aTmpSize.Width() = std::min((long) nBraceHeight * 60L / 100L,
    1689         818 :                             rFormat.GetBaseSize().Height() * 3L / 2L);
    1690             :         // correction factor since change from StarMath to OpenSymbol font
    1691             :         // because of the different font width in the FontMetric
    1692         409 :         aTmpSize.Width() *= 182;
    1693         409 :         aTmpSize.Width() /= 267;
    1694             : 
    1695         409 :         sal_Unicode cChar = pLeft->GetToken().cMathChar;
    1696         409 :         if (cChar != MS_LINE  &&  cChar != MS_DLINE &&
    1697         391 :             cChar != MS_VERTLINE  &&  cChar != MS_DVERTLINE)
    1698         373 :             pLeft ->GetFont().SetSize(aTmpSize);
    1699             : 
    1700         409 :         cChar = pRight->GetToken().cMathChar;
    1701         409 :         if (cChar != MS_LINE  &&  cChar != MS_DLINE &&
    1702         391 :             cChar != MS_VERTLINE  &&  cChar != MS_DVERTLINE)
    1703         373 :             pRight->GetFont().SetSize(aTmpSize);
    1704             : 
    1705         409 :         pLeft ->AdaptToY(rDev, nBraceHeight);
    1706         409 :         pRight->AdaptToY(rDev, nBraceHeight);
    1707             :     }
    1708             : 
    1709         442 :     pLeft ->Arrange(rDev, rFormat);
    1710         442 :     pRight->Arrange(rDev, rFormat);
    1711             : 
    1712             :     // required in order to make "\(a\) - (a) - left ( a right )" look alright
    1713         442 :     RectVerAlign  eVerAlign = bScale ? RVA_CENTERY : RVA_BASELINE;
    1714             : 
    1715         442 :     Point         aPos;
    1716         442 :     aPos = pLeft->AlignTo(*pBody, RP_LEFT, RHA_CENTER, eVerAlign);
    1717         442 :     aPos.X() -= nDist;
    1718         442 :     pLeft->MoveTo(aPos);
    1719             : 
    1720         442 :     aPos = pRight->AlignTo(*pBody, RP_RIGHT, RHA_CENTER, eVerAlign);
    1721         442 :     aPos.X() += nDist;
    1722         442 :     pRight->MoveTo(aPos);
    1723             : 
    1724         442 :     SmRect::operator = (*pBody);
    1725         442 :     ExtendBy(*pLeft, RCP_THIS).ExtendBy(*pRight, RCP_THIS);
    1726         442 : }
    1727             : 
    1728             : 
    1729             : /**************************************************************************/
    1730             : 
    1731             : 
    1732         442 : void SmBracebodyNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1733             : {
    1734         442 :     sal_uInt16  nNumSubNodes = GetNumSubNodes();
    1735         442 :     if (nNumSubNodes == 0)
    1736         475 :         return;
    1737             : 
    1738             :     // arrange arguments
    1739             :     sal_uInt16 i;
    1740         872 :     for (i = 0;  i < nNumSubNodes;  i += 2)
    1741         463 :         GetSubNode(i)->Arrange(rDev, rFormat);
    1742             : 
    1743             :     // build reference rectangle with necessary info for vertical alignment
    1744         409 :     SmRect  aRefRect (*GetSubNode(0));
    1745         872 :     for (i = 0;  i < nNumSubNodes;  i += 2)
    1746             :     {
    1747         463 :         SmRect aTmpRect (*GetSubNode(i));
    1748         463 :         Point  aPos = aTmpRect.AlignTo(aRefRect, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
    1749         463 :         aTmpRect.MoveTo(aPos);
    1750         463 :         aRefRect.ExtendBy(aTmpRect, RCP_XOR);
    1751             :     }
    1752             : 
    1753         409 :     nBodyHeight = aRefRect.GetHeight();
    1754             : 
    1755             :     // scale separators to required height and arrange them
    1756         409 :     bool bScale  = GetScaleMode() == SCALE_HEIGHT  ||  rFormat.IsScaleNormalBrackets();
    1757         409 :     long nHeight = bScale ? aRefRect.GetHeight() : GetFont().GetSize().Height();
    1758         409 :     sal_uInt16 nIndex  = GetScaleMode() == SCALE_HEIGHT ?
    1759         409 :                         DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE;
    1760         409 :     sal_uInt16 nPerc   = rFormat.GetDistance(nIndex);
    1761         409 :     if (bScale)
    1762         409 :         nHeight += 2 * (nHeight * nPerc / 100L);
    1763         463 :     for (i = 1;  i < nNumSubNodes;  i += 2)
    1764             :     {
    1765          54 :         SmNode *pNode = GetSubNode(i);
    1766          54 :         pNode->AdaptToY(rDev, nHeight);
    1767          54 :         pNode->Arrange(rDev, rFormat);
    1768             :     }
    1769             : 
    1770             :     // horizontal distance between argument and brackets or separators
    1771         409 :     long  nDist = GetFont().GetSize().Height()
    1772         409 :                   * rFormat.GetDistance(DIS_BRACKETSPACE) / 100L;
    1773             : 
    1774         409 :     SmNode *pLeft = GetSubNode(0);
    1775         409 :     SmRect::operator = (*pLeft);
    1776         517 :     for (i = 1;  i < nNumSubNodes;  i++)
    1777             :     {
    1778         108 :         bool          bIsSeparator = i % 2 != 0;
    1779         108 :         RectVerAlign  eVerAlign    = bIsSeparator ? RVA_CENTERY : RVA_BASELINE;
    1780             : 
    1781         108 :         SmNode *pRight = GetSubNode(i);
    1782         108 :         Point  aPosX = pRight->AlignTo(*pLeft,   RP_RIGHT, RHA_CENTER, eVerAlign),
    1783         108 :                aPosY = pRight->AlignTo(aRefRect, RP_RIGHT, RHA_CENTER, eVerAlign);
    1784         108 :         aPosX.X() += nDist;
    1785             : 
    1786         108 :         pRight->MoveTo(Point(aPosX.X(), aPosY.Y()));
    1787         108 :         ExtendBy(*pRight, bIsSeparator ? RCP_THIS : RCP_XOR);
    1788             : 
    1789         108 :         pLeft = pRight;
    1790             :     }
    1791             : }
    1792             : 
    1793             : 
    1794             : /**************************************************************************/
    1795             : 
    1796             : 
    1797          36 : void SmVerticalBraceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1798             : {
    1799          36 :     SmNode *pBody   = GetSubNode(0),
    1800          36 :            *pBrace  = GetSubNode(1),
    1801          36 :            *pScript = GetSubNode(2);
    1802             :     OSL_ENSURE(pBody,   "Sm: NULL pointer!");
    1803             :     OSL_ENSURE(pBrace,  "Sm: NULL pointer!");
    1804             :     OSL_ENSURE(pScript, "Sm: NULL pointer!");
    1805             : 
    1806          36 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    1807          36 :     aTmpDev.SetFont(GetFont());
    1808             : 
    1809          36 :     pBody->Arrange(aTmpDev, rFormat);
    1810             : 
    1811             :     // size is the same as for limits for this part
    1812          36 :     pScript->SetSize( Fraction( rFormat.GetRelSize(SIZ_LIMITS), 100 ) );
    1813             :     // braces are a bit taller than usually
    1814          36 :     pBrace ->SetSize( Fraction(3, 2) );
    1815             : 
    1816          36 :     long  nItalicWidth = pBody->GetItalicWidth();
    1817          36 :     if (nItalicWidth > 0)
    1818          36 :         pBrace->AdaptToX(aTmpDev, nItalicWidth);
    1819             : 
    1820          36 :     pBrace ->Arrange(aTmpDev, rFormat);
    1821          36 :     pScript->Arrange(aTmpDev, rFormat);
    1822             : 
    1823             :     // determine the relative position and the distances between each other
    1824             :     RectPos  eRectPos;
    1825          36 :     long nFontHeight = pBody->GetFont().GetSize().Height();
    1826          36 :     long nDistBody   = nFontHeight * rFormat.GetDistance(DIS_ORNAMENTSIZE),
    1827          36 :          nDistScript = nFontHeight;
    1828          36 :     if (GetToken().eType == TOVERBRACE)
    1829             :     {
    1830          18 :         eRectPos = RP_TOP;
    1831          18 :         nDistBody    = - nDistBody;
    1832          18 :         nDistScript *= - rFormat.GetDistance(DIS_UPPERLIMIT);
    1833             :     }
    1834             :     else // TUNDERBRACE
    1835             :     {
    1836          18 :         eRectPos = RP_BOTTOM;
    1837          18 :         nDistScript *= + rFormat.GetDistance(DIS_LOWERLIMIT);
    1838             :     }
    1839          36 :     nDistBody   /= 100L;
    1840          36 :     nDistScript /= 100L;
    1841             : 
    1842          36 :     Point  aPos = pBrace->AlignTo(*pBody, eRectPos, RHA_CENTER, RVA_BASELINE);
    1843          36 :     aPos.Y() += nDistBody;
    1844          36 :     pBrace->MoveTo(aPos);
    1845             : 
    1846          36 :     aPos = pScript->AlignTo(*pBrace, eRectPos, RHA_CENTER, RVA_BASELINE);
    1847          36 :     aPos.Y() += nDistScript;
    1848          36 :     pScript->MoveTo(aPos);
    1849             : 
    1850          36 :     SmRect::operator = (*pBody);
    1851          36 :     ExtendBy(*pBrace, RCP_THIS).ExtendBy(*pScript, RCP_THIS);
    1852          36 : }
    1853             : 
    1854             : 
    1855             : /**************************************************************************/
    1856             : 
    1857             : 
    1858         164 : SmNode * SmOperNode::GetSymbol()
    1859             : {
    1860         164 :     SmNode *pNode = GetSubNode(0);
    1861             :     OSL_ENSURE(pNode, "Sm: NULL pointer!");
    1862             : 
    1863         164 :     if (pNode->GetType() == NSUBSUP)
    1864         161 :         pNode = static_cast<SmSubSupNode *>(pNode)->GetBody();
    1865             : 
    1866             :     OSL_ENSURE(pNode, "Sm: NULL pointer!");
    1867         164 :     return pNode;
    1868             : }
    1869             : 
    1870             : 
    1871         162 : long SmOperNode::CalcSymbolHeight(const SmNode &rSymbol,
    1872             :                                   const SmFormat &rFormat) const
    1873             :     // returns the font height to be used for operator-symbol
    1874             : {
    1875         162 :     long  nHeight = GetFont().GetSize().Height();
    1876             : 
    1877         162 :     SmTokenType  eTmpType = GetToken().eType;
    1878         162 :     if (eTmpType == TLIM  ||  eTmpType == TLIMINF  ||  eTmpType == TLIMSUP)
    1879          15 :         return nHeight;
    1880             : 
    1881         147 :     if (!rFormat.IsTextmode())
    1882             :     {
    1883             :         // set minimum size ()
    1884         147 :         nHeight += (nHeight * 20L) / 100L;
    1885             : 
    1886             :         nHeight += nHeight
    1887         147 :                    * rFormat.GetDistance(DIS_OPERATORSIZE) / 100L;
    1888         147 :         nHeight = nHeight * 686L / 845L;
    1889             :     }
    1890             : 
    1891             :     // correct user-defined symbols to match height of sum from used font
    1892         147 :     if (rSymbol.GetToken().eType == TSPECIAL)
    1893           0 :         nHeight = nHeight * 845L / 686L;
    1894             : 
    1895         147 :     return nHeight;
    1896             : }
    1897             : 
    1898             : 
    1899         162 : void SmOperNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1900             : {
    1901         162 :     SmNode *pOper = GetSubNode(0);
    1902         162 :     SmNode *pBody = GetSubNode(1);
    1903             : 
    1904             :     OSL_ENSURE(pOper, "Sm: missing subnode");
    1905             :     OSL_ENSURE(pBody, "Sm: missing subnode");
    1906             : 
    1907         162 :     SmNode *pSymbol = GetSymbol();
    1908             :     pSymbol->SetSize(Fraction(CalcSymbolHeight(*pSymbol, rFormat),
    1909         162 :                               pSymbol->GetFont().GetSize().Height()));
    1910             : 
    1911         162 :     pBody->Arrange(rDev, rFormat);
    1912         162 :     pOper->Arrange(rDev, rFormat);
    1913             : 
    1914         162 :     long  nOrigHeight = GetFont().GetSize().Height(),
    1915             :           nDist = nOrigHeight
    1916         162 :                   * rFormat.GetDistance(DIS_OPERATORSPACE) / 100L;
    1917             : 
    1918         162 :     Point aPos = pOper->AlignTo(*pBody, RP_LEFT, RHA_CENTER, /*RVA_CENTERY*/RVA_MID);
    1919         162 :     aPos.X() -= nDist;
    1920         162 :     pOper->MoveTo(aPos);
    1921             : 
    1922         162 :     SmRect::operator = (*pBody);
    1923         162 :     ExtendBy(*pOper, RCP_THIS);
    1924         162 : }
    1925             : 
    1926             : 
    1927             : /**************************************************************************/
    1928             : 
    1929             : 
    1930           0 : void SmAlignNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1931             :     // set alignment within the entire subtree (including current node)
    1932             : {
    1933             :     OSL_ENSURE(GetNumSubNodes() > 0, "Sm: missing subnode");
    1934             : 
    1935           0 :     SmNode  *pNode = GetSubNode(0);
    1936             : 
    1937           0 :     RectHorAlign  eHorAlign = RHA_CENTER;
    1938           0 :     switch (GetToken().eType)
    1939             :     {
    1940           0 :         case TALIGNL:   eHorAlign = RHA_LEFT;   break;
    1941           0 :         case TALIGNC:   eHorAlign = RHA_CENTER; break;
    1942           0 :         case TALIGNR:   eHorAlign = RHA_RIGHT;  break;
    1943             :         default:
    1944           0 :             break;
    1945             :     }
    1946           0 :     SetRectHorAlign(eHorAlign);
    1947             : 
    1948           0 :     pNode->Arrange(rDev, rFormat);
    1949             : 
    1950           0 :     SmRect::operator = (pNode->GetRect());
    1951           0 : }
    1952             : 
    1953             : 
    1954             : /**************************************************************************/
    1955             : 
    1956             : 
    1957         254 : void SmAttributNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    1958             : {
    1959         254 :     SmNode *pAttr = GetSubNode(0),
    1960         254 :            *pBody = GetSubNode(1);
    1961             :     OSL_ENSURE(pBody, "Sm: body missing");
    1962             :     OSL_ENSURE(pAttr, "Sm: attribute missing");
    1963             : 
    1964         254 :     pBody->Arrange(rDev, rFormat);
    1965             : 
    1966         254 :     if (GetScaleMode() == SCALE_WIDTH)
    1967         144 :         pAttr->AdaptToX(rDev, pBody->GetItalicWidth());
    1968         254 :     pAttr->Arrange(rDev, rFormat);
    1969             : 
    1970             :     // get relative position of attribute
    1971             :     RectVerAlign  eVerAlign;
    1972         254 :     long          nDist = 0;
    1973         254 :     switch (GetToken().eType)
    1974             :     {   case TUNDERLINE :
    1975          18 :             eVerAlign = RVA_ATTRIBUT_LO;
    1976          18 :             break;
    1977             :         case TOVERSTRIKE :
    1978          18 :             eVerAlign = RVA_ATTRIBUT_MID;
    1979          18 :             break;
    1980             :         default :
    1981         218 :             eVerAlign = RVA_ATTRIBUT_HI;
    1982         218 :             if (pBody->GetType() == NATTRIBUT)
    1983           0 :                 nDist = GetFont().GetSize().Height()
    1984           0 :                         * rFormat.GetDistance(DIS_ORNAMENTSPACE) / 100L;
    1985             :     }
    1986         254 :     Point  aPos = pAttr->AlignTo(*pBody, RP_ATTRIBUT, RHA_CENTER, eVerAlign);
    1987         254 :     aPos.Y() -= nDist;
    1988         254 :     pAttr->MoveTo(aPos);
    1989             : 
    1990         254 :     SmRect::operator = (*pBody);
    1991         254 :     ExtendBy(*pAttr, RCP_THIS, true);
    1992         254 : }
    1993             : 
    1994           0 : void SmFontNode::CreateTextFromNode(OUString &rText)
    1995             : {
    1996           0 :     switch (GetToken().eType)
    1997             :     {
    1998             :         case TBOLD:
    1999           0 :             rText += "bold ";
    2000           0 :             break;
    2001             :         case TNBOLD:
    2002           0 :             rText += "nbold ";
    2003           0 :             break;
    2004             :         case TITALIC:
    2005           0 :             rText += "italic ";
    2006           0 :             break;
    2007             :         case TNITALIC:
    2008           0 :             rText += "nitalic ";
    2009           0 :             break;
    2010             :         case TPHANTOM:
    2011           0 :             rText += "phantom ";
    2012           0 :             break;
    2013             :         case TSIZE:
    2014             :             {
    2015           0 :                 rText += "size ";
    2016           0 :                 switch (nSizeType)
    2017             :                 {
    2018             :                     case FontSizeType::PLUS:
    2019           0 :                         rText += "+";
    2020           0 :                         break;
    2021             :                     case FontSizeType::MINUS:
    2022           0 :                         rText += "-";
    2023           0 :                         break;
    2024             :                     case FontSizeType::MULTIPLY:
    2025           0 :                         rText += "*";
    2026           0 :                         break;
    2027             :                     case FontSizeType::DIVIDE:
    2028           0 :                         rText += "/";
    2029           0 :                         break;
    2030             :                     case FontSizeType::ABSOLUT:
    2031             :                     default:
    2032           0 :                         break;
    2033             :                 }
    2034           0 :                 rText += ::rtl::math::doubleToUString(
    2035             :                             static_cast<double>(aFontSize),
    2036             :                             rtl_math_StringFormat_Automatic,
    2037           0 :                             rtl_math_DecimalPlaces_Max, '.', true);
    2038           0 :                 rText += " ";
    2039             :             }
    2040           0 :             break;
    2041             :         case TBLACK:
    2042           0 :             rText += "color black ";
    2043           0 :             break;
    2044             :         case TWHITE:
    2045           0 :             rText += "color white ";
    2046           0 :             break;
    2047             :         case TRED:
    2048           0 :             rText += "color red ";
    2049           0 :             break;
    2050             :         case TGREEN:
    2051           0 :             rText += "color green ";
    2052           0 :             break;
    2053             :         case TBLUE:
    2054           0 :             rText += "color blue ";
    2055           0 :             break;
    2056             :         case TCYAN:
    2057           0 :             rText += "color cyan ";
    2058           0 :             break;
    2059             :         case TMAGENTA:
    2060           0 :             rText += "color magenta ";
    2061           0 :             break;
    2062             :         case TYELLOW:
    2063           0 :             rText += "color yellow ";
    2064           0 :             break;
    2065             :         case TTEAL:
    2066           0 :             rText += "color teal";
    2067           0 :             break;
    2068             :         case TSILVER:
    2069           0 :             rText += "color silver";
    2070           0 :             break;
    2071             :         case TGRAY:
    2072           0 :             rText += "color gray";
    2073           0 :             break;
    2074             :         case TMAROON:
    2075           0 :             rText += "color maroon";
    2076           0 :             break;
    2077             :         case TPURPLE:
    2078           0 :             rText += "color purple";
    2079           0 :             break;
    2080             :         case TLIME:
    2081           0 :             rText += "color lime";
    2082           0 :             break;
    2083             :         case TOLIVE:
    2084           0 :             rText += "color olive";
    2085           0 :             break;
    2086             :         case TNAVY:
    2087           0 :             rText += "color navy";
    2088           0 :             break;
    2089             :         case TAQUA:
    2090           0 :             rText += "color aqua";
    2091           0 :             break;
    2092             :         case TFUCHSIA:
    2093           0 :             rText += "color fuchsia";
    2094           0 :             break;
    2095             :         case TSANS:
    2096           0 :             rText += "font sans ";
    2097           0 :             break;
    2098             :         case TSERIF:
    2099           0 :             rText += "font serif ";
    2100           0 :             break;
    2101             :         case TFIXED:
    2102           0 :             rText += "font fixed ";
    2103           0 :             break;
    2104             :         default:
    2105           0 :             break;
    2106             :     }
    2107           0 :     GetSubNode(1)->CreateTextFromNode(rText);
    2108           0 : }
    2109             : 
    2110         125 : void SmFontNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
    2111             : {
    2112             :     //! prepare subnodes first
    2113         125 :     SmNode::Prepare(rFormat, rDocShell);
    2114             : 
    2115         125 :     int  nFnt = -1;
    2116         125 :     switch (GetToken().eType)
    2117             :     {
    2118           2 :         case TFIXED:    nFnt = FNT_FIXED;   break;
    2119           2 :         case TSANS:     nFnt = FNT_SANS;    break;
    2120           2 :         case TSERIF:    nFnt = FNT_SERIF;   break;
    2121             :         default:
    2122         119 :             break;
    2123             :     }
    2124         125 :     if (nFnt != -1)
    2125           6 :     {   GetFont() = rFormat.GetFont( sal::static_int_cast< sal_uInt16 >(nFnt) );
    2126           6 :         SetFont(GetFont());
    2127             :     }
    2128             : 
    2129             :     //! prevent overwrites of this font by 'Arrange' or 'SetFont' calls of
    2130             :     //! other font nodes (those with lower depth in the tree)
    2131         125 :     Flags() |= FLG_FONT;
    2132         125 : }
    2133             : 
    2134          91 : void SmFontNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    2135             : {
    2136          91 :     SmNode *pNode = GetSubNode(1);
    2137             :     OSL_ENSURE(pNode, "Sm: missing subnode");
    2138             : 
    2139          91 :     switch (GetToken().eType)
    2140             :     {   case TSIZE :
    2141          66 :             pNode->SetFontSize(aFontSize, nSizeType);
    2142          66 :             break;
    2143             :         case TSANS :
    2144             :         case TSERIF :
    2145             :         case TFIXED :
    2146           0 :             pNode->SetFont(GetFont());
    2147           0 :             break;
    2148           1 :         case TUNKNOWN : break;  // no assertion on "font <?> <?>"
    2149             : 
    2150           0 :         case TPHANTOM : SetPhantom(true);               break;
    2151           0 :         case TBOLD :    SetAttribut(ATTR_BOLD);         break;
    2152          24 :         case TITALIC :  SetAttribut(ATTR_ITALIC);       break;
    2153           0 :         case TNBOLD :   ClearAttribut(ATTR_BOLD);       break;
    2154           0 :         case TNITALIC : ClearAttribut(ATTR_ITALIC);     break;
    2155             : 
    2156           0 :         case TBLACK :   SetColor(Color(COL_BLACK));     break;
    2157           0 :         case TWHITE :   SetColor(Color(COL_WHITE));     break;
    2158           0 :         case TRED :     SetColor(Color(COL_LIGHTRED));      break;
    2159           0 :         case TGREEN :   SetColor(Color(COL_GREEN));     break;
    2160           0 :         case TBLUE :    SetColor(Color(COL_LIGHTBLUE));     break;
    2161           0 :         case TCYAN :    SetColor(Color(COL_LIGHTCYAN));     break; // as in Calc
    2162           0 :         case TMAGENTA : SetColor(Color(COL_LIGHTMAGENTA));  break; // as in Calc
    2163           0 :         case TYELLOW :  SetColor(Color(COL_YELLOW));    break;
    2164           0 :         case TTEAL :    SetColor(Color(COL_CYAN));  break;
    2165           0 :         case TSILVER :  SetColor(Color(COL_LIGHTGRAY));  break;
    2166           0 :         case TGRAY :    SetColor(Color(COL_GRAY));  break;
    2167           0 :         case TMAROON :  SetColor(Color(COL_RED));  break;
    2168           0 :         case TPURPLE :  SetColor(Color(COL_MAGENTA));  break;
    2169           0 :         case TLIME :    SetColor(Color(COL_LIGHTGREEN));  break;
    2170           0 :         case TOLIVE :   SetColor(Color(COL_BROWN));  break;
    2171           0 :         case TNAVY :    SetColor(Color(COL_BLUE));  break;
    2172           0 :         case TAQUA :    SetColor(Color(COL_LIGHTCYAN));  break;
    2173           0 :         case TFUCHSIA : SetColor(Color(COL_LIGHTMAGENTA));  break;
    2174             : 
    2175             :         default:
    2176             :             SAL_WARN("starmath", "unknown case");
    2177             :     }
    2178             : 
    2179          91 :     pNode->Arrange(rDev, rFormat);
    2180             : 
    2181          91 :     SmRect::operator = (pNode->GetRect());
    2182          91 : }
    2183             : 
    2184             : 
    2185          66 : void SmFontNode::SetSizeParameter(const Fraction& rValue, FontSizeType Type)
    2186             : {
    2187          66 :     nSizeType = Type;
    2188          66 :     aFontSize = rValue;
    2189          66 : }
    2190             : 
    2191             : 
    2192             : /**************************************************************************/
    2193             : 
    2194             : 
    2195          34 : SmPolyLineNode::SmPolyLineNode(const SmToken &rNodeToken)
    2196          34 : :   SmGraphicNode(NPOLYLINE, rNodeToken)
    2197             : {
    2198          34 :     aPoly.SetSize(2);
    2199          34 :     nWidth = 0;
    2200          34 : }
    2201             : 
    2202             : 
    2203          34 : void SmPolyLineNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nNewWidth)
    2204             : {
    2205          34 :     aToSize.Width() = nNewWidth;
    2206          34 : }
    2207             : 
    2208             : 
    2209          34 : void SmPolyLineNode::AdaptToY(const OutputDevice &/*rDev*/, sal_uLong nNewHeight)
    2210             : {
    2211          34 :     GetFont().FreezeBorderWidth();
    2212          34 :     aToSize.Height() = nNewHeight;
    2213          34 : }
    2214             : 
    2215             : 
    2216          68 : void SmPolyLineNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    2217             : {
    2218             :     //! some routines being called extract some info from the OutputDevice's
    2219             :     //! font (eg the space to be used for borders OR the font name(!!)).
    2220             :     //! Thus the font should reflect the needs and has to be set!
    2221          68 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    2222          68 :     aTmpDev.SetFont(GetFont());
    2223             : 
    2224          68 :     long  nBorderwidth = GetFont().GetBorderWidth();
    2225             : 
    2226             :     // create polygon using both endpoints
    2227             :     OSL_ENSURE(aPoly.GetSize() == 2, "Sm : wrong number of points");
    2228          68 :     Point  aPointA, aPointB;
    2229          68 :     if (GetToken().eType == TWIDESLASH)
    2230             :     {
    2231          34 :         aPointA.X() = nBorderwidth;
    2232          34 :         aPointA.Y() = aToSize.Height() - nBorderwidth;
    2233          34 :         aPointB.X() = aToSize.Width() - nBorderwidth;
    2234          34 :         aPointB.Y() = nBorderwidth;
    2235             :     }
    2236             :     else
    2237             :     {
    2238             :         OSL_ENSURE(GetToken().eType == TWIDEBACKSLASH, "Sm : unexpected token");
    2239          34 :         aPointA.X() =
    2240          34 :         aPointA.Y() = nBorderwidth;
    2241          34 :         aPointB.X() = aToSize.Width() - nBorderwidth;
    2242          34 :         aPointB.Y() = aToSize.Height() - nBorderwidth;
    2243             :     }
    2244          68 :     aPoly.SetPoint(aPointA, 0);
    2245          68 :     aPoly.SetPoint(aPointB, 1);
    2246             : 
    2247          68 :     long  nThick       = GetFont().GetSize().Height()
    2248          68 :                             * rFormat.GetDistance(DIS_STROKEWIDTH) / 100L;
    2249          68 :     nWidth = nThick + 2 * nBorderwidth;
    2250             : 
    2251          68 :     SmRect::operator = (SmRect(aToSize.Width(), aToSize.Height()));
    2252          68 : }
    2253             : 
    2254             : 
    2255             : /**************************************************************************/
    2256             : 
    2257          78 : void SmRootSymbolNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nWidth)
    2258             : {
    2259          78 :     nBodyWidth = nWidth;
    2260          78 : }
    2261             : 
    2262             : 
    2263          78 : void SmRootSymbolNode::AdaptToY(const OutputDevice &rDev, sal_uLong nHeight)
    2264             : {
    2265             :     // some additional length so that the horizontal
    2266             :     // bar will be positioned above the argument
    2267          78 :     SmMathSymbolNode::AdaptToY(rDev, nHeight + nHeight / 10L);
    2268          78 : }
    2269             : 
    2270             : 
    2271             : /**************************************************************************/
    2272             : 
    2273             : 
    2274           0 : void SmDynIntegralSymbolNode::AdaptToY(const OutputDevice &rDev, sal_uLong nHeight)
    2275             : {
    2276             :     static const long nFactor = 12L;
    2277             : 
    2278             :     // The new height equals (1 + nFactor) * oldHeight
    2279             :     // nFactor was chosen for keeping the integral sign from becoming too "fat".
    2280           0 :     SmMathSymbolNode::AdaptToY(rDev, nHeight + nHeight / nFactor);
    2281             : 
    2282             :     // keep the ratio
    2283           0 :     long nCurWidth = GetSize().Width();
    2284           0 :     SmMathSymbolNode::AdaptToX(rDev, nCurWidth + nCurWidth / nFactor);
    2285           0 : }
    2286             : 
    2287             : 
    2288             : /**************************************************************************/
    2289             : 
    2290             : 
    2291         275 : void SmRectangleNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nWidth)
    2292             : {
    2293         275 :     aToSize.Width() = nWidth;
    2294         275 : }
    2295             : 
    2296             : 
    2297         239 : void SmRectangleNode::AdaptToY(const OutputDevice &/*rDev*/, sal_uLong nHeight)
    2298             : {
    2299         239 :     GetFont().FreezeBorderWidth();
    2300         239 :     aToSize.Height() = nHeight;
    2301         239 : }
    2302             : 
    2303             : 
    2304         275 : void SmRectangleNode::Arrange(const OutputDevice &rDev, const SmFormat &/*rFormat*/)
    2305             : {
    2306         275 :     long  nFontHeight = GetFont().GetSize().Height();
    2307         275 :     long  nWidth  = aToSize.Width(),
    2308         275 :           nHeight = aToSize.Height();
    2309         275 :     if (nHeight == 0)
    2310          36 :         nHeight = nFontHeight / 30;
    2311         275 :     if (nWidth == 0)
    2312           0 :         nWidth  = nFontHeight / 3;
    2313             : 
    2314         275 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    2315         275 :     aTmpDev.SetFont(GetFont());
    2316             : 
    2317             :     // add some borderspace
    2318         275 :     sal_uLong  nTmpBorderWidth = GetFont().GetBorderWidth();
    2319         275 :     nHeight += 2 * nTmpBorderWidth;
    2320             : 
    2321             :     //! use this method in order to have 'SmRect::HasAlignInfo() == true'
    2322             :     //! and thus having the attribute-fences updated in 'SmRect::ExtendBy'
    2323         275 :     SmRect::operator = (SmRect(nWidth, nHeight));
    2324         275 : }
    2325             : 
    2326             : 
    2327             : /**************************************************************************/
    2328             : 
    2329             : 
    2330        3692 : SmTextNode::SmTextNode( SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 nFontDescP )
    2331             :     : SmVisibleNode(eNodeType, rNodeToken)
    2332             :     , nFontDesc(nFontDescP)
    2333             :     , nSelectionStart(0)
    2334        3692 :     , nSelectionEnd(0)
    2335             : {
    2336        3692 : }
    2337             : 
    2338        4940 : SmTextNode::SmTextNode( const SmToken &rNodeToken, sal_uInt16 nFontDescP )
    2339             :     : SmVisibleNode(NTEXT, rNodeToken)
    2340             :     , nFontDesc(nFontDescP)
    2341             :     , nSelectionStart(0)
    2342        4940 :     , nSelectionEnd(0)
    2343             : {
    2344        4940 : }
    2345             : 
    2346        4925 : void SmTextNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
    2347             : {
    2348        4925 :     SmNode::Prepare(rFormat, rDocShell);
    2349             : 
    2350             :     // default setting for horizontal alignment of nodes with TTEXT
    2351             :     // content is as alignl (cannot be done in Arrange since it would
    2352             :     // override the settings made by an SmAlignNode before)
    2353        4925 :     if (TTEXT == GetToken().eType)
    2354         102 :         SetRectHorAlign( RHA_LEFT );
    2355             : 
    2356        4925 :     aText = GetToken().aText;
    2357        4925 :     GetFont() = rFormat.GetFont(GetFontDesc());
    2358             : 
    2359        4925 :     if (IsItalic( GetFont() ))
    2360        3449 :         Attributes() |= ATTR_ITALIC;
    2361        4925 :     if (IsBold( GetFont() ))
    2362          32 :         Attributes() |= ATTR_BOLD;
    2363             : 
    2364             :     // special handling for ':' where it is a token on it's own and is likely
    2365             :     // to be used for mathematical notations. (E.g. a:b = 2:3)
    2366             :     // In that case it should not be displayed in italic.
    2367        4925 :     if (GetToken().aText.getLength() == 1 && GetToken().aText[0] == ':')
    2368           0 :         Attributes() &= ~ATTR_ITALIC;
    2369        4925 : };
    2370             : 
    2371             : 
    2372        4268 : void SmTextNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    2373             : {
    2374        4268 :     PrepareAttributes();
    2375             : 
    2376        4268 :     sal_uInt16  nSizeDesc = GetFontDesc() == FNT_FUNCTION ?
    2377        4268 :                             SIZ_FUNCTION : SIZ_TEXT;
    2378        4268 :     GetFont() *= Fraction (rFormat.GetRelSize(nSizeDesc), 100);
    2379             : 
    2380        4268 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    2381        4268 :     aTmpDev.SetFont(GetFont());
    2382             : 
    2383        4268 :     SmRect::operator = (SmRect(aTmpDev, &rFormat, aText, GetFont().GetBorderWidth()));
    2384        4268 : }
    2385             : 
    2386           9 : void SmTextNode::CreateTextFromNode(OUString &rText)
    2387             : {
    2388           9 :     bool bQuoted=false;
    2389           9 :     if (GetToken().eType == TTEXT)
    2390             :     {
    2391           0 :         rText += "\"";
    2392           0 :         bQuoted=true;
    2393             :     }
    2394             :     else
    2395             :     {
    2396           9 :         SmParser aParseTest;
    2397           9 :         SmNode *pTable = aParseTest.Parse(GetToken().aText);
    2398           9 :         bQuoted=true;
    2399           9 :         if ( (pTable->GetType() == NTABLE) && (pTable->GetNumSubNodes() == 1) )
    2400             :         {
    2401           9 :             SmNode *pResult = pTable->GetSubNode(0);
    2402          18 :             if ( (pResult->GetType() == NLINE) &&
    2403           9 :                 (pResult->GetNumSubNodes() == 1) )
    2404             :             {
    2405           9 :                 pResult = pResult->GetSubNode(0);
    2406           9 :                 if ( (pResult->GetType() == NEXPRESSION) &&
    2407           0 :                     (pResult->GetNumSubNodes() == 1) )
    2408             :                 {
    2409           0 :                     pResult = pResult->GetSubNode(0);
    2410           0 :                     if (pResult->GetType() == NTEXT)
    2411           0 :                         bQuoted=false;
    2412             :                 }
    2413             :             }
    2414             :         }
    2415           9 :         delete pTable;
    2416             : 
    2417           9 :         if ((GetToken().eType == TIDENT) && (GetFontDesc() == FNT_FUNCTION))
    2418             :         {
    2419             :             //Search for existing functions and remove extraenous keyword
    2420           0 :             rText += "func ";
    2421             :         }
    2422           9 :         else if (bQuoted)
    2423           9 :             rText += "italic ";
    2424             : 
    2425           9 :         if (bQuoted)
    2426           9 :             rText += "\"";
    2427             : 
    2428             :     }
    2429             : 
    2430           9 :     rText += GetToken().aText;
    2431             : 
    2432           9 :     if (bQuoted)
    2433           9 :         rText += "\"";
    2434           9 :     rText += " ";
    2435           9 : }
    2436             : 
    2437             : 
    2438           0 : void SmTextNode::GetAccessibleText( OUStringBuffer &rText ) const
    2439             : {
    2440           0 :     rText.append(aText);
    2441           0 : }
    2442             : 
    2443          13 : void SmTextNode::AdjustFontDesc()
    2444             : {
    2445          13 :     if (GetToken().eType == TTEXT)
    2446           0 :         nFontDesc = FNT_TEXT;
    2447          13 :     else if(GetToken().eType == TFUNC)
    2448           0 :         nFontDesc = FNT_FUNCTION;
    2449             :     else {
    2450             :         SmTokenType nTok;
    2451          13 :         const SmTokenTableEntry *pEntry = SmParser::GetTokenTableEntry( aText );
    2452          13 :         if (pEntry && pEntry->nGroup == TGFUNCTION) {
    2453           0 :             nTok = pEntry->eType;
    2454           0 :             nFontDesc = FNT_FUNCTION;
    2455             :         } else {
    2456          13 :             sal_Unicode firstChar = aText[0];
    2457          13 :             if( ('0' <= firstChar && firstChar <= '9') || firstChar == '.' || firstChar == ',') {
    2458           6 :                 nFontDesc = FNT_NUMBER;
    2459           6 :                 nTok = TNUMBER;
    2460           7 :             } else if (aText.getLength() > 1) {
    2461           0 :                 nFontDesc = FNT_VARIABLE;
    2462           0 :                 nTok = TIDENT;
    2463             :             } else {
    2464           7 :                 nFontDesc = FNT_VARIABLE;
    2465           7 :                 nTok = TCHARACTER;
    2466             :             }
    2467             :         }
    2468          13 :         SmToken tok = GetToken();
    2469          13 :         tok.eType = nTok;
    2470          13 :         SetToken(tok);
    2471             :     }
    2472          13 : }
    2473             : 
    2474         900 : sal_Unicode SmTextNode::ConvertSymbolToUnicode(sal_Unicode nIn)
    2475             : {
    2476             :     //Find the best match in accepted unicode for our private area symbols
    2477             :     static const sal_Unicode aStarMathPrivateToUnicode[] =
    2478             :     {
    2479             :         0x2030, 0xF613, 0xF612, 0x002B, 0x003C, 0x003E, 0xE425, 0xE421, 0xE088, 0x2208,
    2480             :         0x0192, 0x2026, 0x2192, 0x221A, 0x221A, 0x221A, 0xE090, 0x005E, 0x02C7, 0x02D8,
    2481             :         0x00B4, 0x0060, 0x02DC, 0x00AF, 0x0362, 0xE099, 0xE09A, 0x20DB, 0xE09C, 0xE09D,
    2482             :         0x0028, 0x0029, 0x2220, 0x22AF, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7,
    2483             :         0x002F, 0x005C, 0x274F, 0xE0AB, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03A0,
    2484             :         0x03a3, 0x03a5, 0x03a6, 0x03a8, 0x03A9, 0x03B1, 0x03B2, 0x03b3, 0x03b4, 0x03b5,
    2485             :         0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
    2486             :         0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03b5,
    2487             :         0x03d1, 0x03d6, 0xE0D2, 0x03db, 0x2118, 0x2202, 0x2129, 0xE0D7, 0xE0D8, 0x22A4,
    2488             :         0xE0DA, 0x2190, 0x2191, 0x2193
    2489             :     };
    2490         900 :     if ((nIn >= 0xE080) && (nIn <= 0xE0DD))
    2491           0 :         nIn = aStarMathPrivateToUnicode[nIn-0xE080];
    2492             : 
    2493             :     //For whatever unicode glyph that equation editor doesn't ship with that
    2494             :     //we have a possible match we can munge it to.
    2495         900 :     switch (nIn)
    2496             :     {
    2497             :         case 0x2223:
    2498           0 :             nIn = '|';
    2499           0 :             break;
    2500             :         default:
    2501         900 :             break;
    2502             :     }
    2503             : 
    2504         900 :     return nIn;
    2505             : }
    2506             : 
    2507             : /**************************************************************************/
    2508             : 
    2509           1 : void SmMatrixNode::CreateTextFromNode(OUString &rText)
    2510             : {
    2511           1 :     rText += "matrix {";
    2512           4 :     for (sal_uInt16 i = 0;  i < nNumRows; i++)
    2513             :     {
    2514           6 :         for (sal_uInt16 j = 0;  j < nNumCols; j++)
    2515             :         {
    2516           3 :             SmNode *pNode = GetSubNode(i * nNumCols + j);
    2517           3 :             if (pNode)
    2518           3 :                 pNode->CreateTextFromNode(rText);
    2519           3 :             if (j != nNumCols-1)
    2520           0 :                 rText += "# ";
    2521             :         }
    2522           3 :         if (i != nNumRows-1)
    2523           2 :             rText += "## ";
    2524             :     }
    2525           1 :     rText = comphelper::string::stripEnd(rText, ' ');
    2526           1 :     rText += "} ";
    2527           1 : }
    2528             : 
    2529             : 
    2530          20 : void SmMatrixNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    2531             : {
    2532             :     SmNode *pNode;
    2533             :     sal_uInt16  i, j;
    2534             : 
    2535             :     // initialize array that is to hold the maximum widths of all
    2536             :     // elements (subnodes) in that column.
    2537          20 :     std::vector<long> aColWidth(nNumCols);
    2538             : 
    2539             :     // arrange subnodes and calculate the aboves arrays contents
    2540          20 :     sal_uInt16 nNodes = GetNumSubNodes();
    2541          98 :     for (i = 0;  i < nNodes;  i++)
    2542             :     {
    2543          78 :         sal_uInt16 nIdx = nNodes - 1 - i;
    2544          78 :         if (NULL != (pNode = GetSubNode(nIdx)))
    2545             :         {
    2546          78 :             pNode->Arrange(rDev, rFormat);
    2547          78 :             int  nCol = nIdx % nNumCols;
    2548          78 :             aColWidth[nCol] = std::max(aColWidth[nCol], pNode->GetItalicWidth());
    2549             :         }
    2550             :     }
    2551             : 
    2552             :     // norm distance from which the following two are calcutated
    2553          20 :     const long  nNormDist = 3 * GetFont().GetSize().Height();
    2554             : 
    2555             :     // define horizontal and vertical minimal distances that separate
    2556             :     // the elements
    2557          20 :     long  nHorDist = nNormDist * rFormat.GetDistance(DIS_MATRIXCOL) / 100L,
    2558          20 :           nVerDist = nNormDist * rFormat.GetDistance(DIS_MATRIXROW) / 100L;
    2559             : 
    2560             :     // build array that holds the leftmost position for each column
    2561          40 :     std::vector<long> aColLeft(nNumCols);
    2562          20 :     long  nX = 0;
    2563          58 :     for (j = 0;  j < nNumCols;  j++)
    2564             :     {
    2565          38 :         aColLeft[j] = nX;
    2566          38 :         nX += aColWidth[j] + nHorDist;
    2567             :     }
    2568             : 
    2569          20 :     Point   aPos, aDelta;
    2570          20 :     SmRect  aLineRect;
    2571          20 :     SmRect::operator = (SmRect());
    2572          62 :     for (i = 0;  i < nNumRows;  i++)
    2573          42 :     {   aLineRect = SmRect();
    2574         120 :         for (j = 0;  j < nNumCols;  j++)
    2575          78 :         {   SmNode *pTmpNode = GetSubNode(i * nNumCols + j);
    2576             :             OSL_ENSURE(pTmpNode, "Sm: NULL pointer");
    2577             : 
    2578          78 :             const SmRect &rNodeRect = pTmpNode->GetRect();
    2579             : 
    2580             :             // align all baselines in that row if possible
    2581          78 :             aPos = rNodeRect.AlignTo(aLineRect, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
    2582          78 :             aPos.X() += nHorDist;
    2583             : 
    2584             :             // get horizontal alignment
    2585          78 :             const SmNode *pCoNode   = pTmpNode->GetLeftMost();
    2586          78 :             RectHorAlign  eHorAlign = pCoNode->GetRectHorAlign();
    2587             : 
    2588             :             // calculate horizontal position of element depending on column
    2589             :             // and horizontal alignment
    2590          78 :             switch (eHorAlign)
    2591             :             {   case RHA_LEFT:
    2592           0 :                     aPos.X() = rNodeRect.GetLeft() + aColLeft[j];
    2593           0 :                     break;
    2594             :                 case RHA_CENTER:
    2595          78 :                     aPos.X() = rNodeRect.GetLeft() + aColLeft[j]
    2596          78 :                                + aColWidth[j] / 2
    2597          78 :                                - rNodeRect.GetItalicCenterX();
    2598          78 :                     break;
    2599             :                 case RHA_RIGHT:
    2600           0 :                     aPos.X() = rNodeRect.GetLeft() + aColLeft[j]
    2601           0 :                                + aColWidth[j] - rNodeRect.GetItalicWidth();
    2602           0 :                     break;
    2603             :             }
    2604             : 
    2605          78 :             pTmpNode->MoveTo(aPos);
    2606          78 :             aLineRect.ExtendBy(rNodeRect, RCP_XOR);
    2607             :         }
    2608             : 
    2609          42 :         aPos = aLineRect.AlignTo(*this, RP_BOTTOM, RHA_CENTER, RVA_BASELINE);
    2610          42 :         aPos.Y() += nVerDist;
    2611             : 
    2612             :         // move 'aLineRect' and rectangles in that line to final position
    2613          42 :         aDelta.X() = 0;     // since horizontal alignment is already done
    2614          42 :         aDelta.Y() = aPos.Y() - aLineRect.GetTop();
    2615          42 :         aLineRect.Move(aDelta);
    2616         120 :         for (j = 0;  j < nNumCols;  j++)
    2617          78 :             if (NULL != (pNode = GetSubNode(i * nNumCols + j)))
    2618          78 :                 pNode->Move(aDelta);
    2619             : 
    2620          42 :         ExtendBy(aLineRect, RCP_NONE);
    2621          20 :     }
    2622          20 : }
    2623             : 
    2624             : 
    2625          25 : void SmMatrixNode::SetRowCol(sal_uInt16 nMatrixRows, sal_uInt16 nMatrixCols)
    2626             : {
    2627          25 :     nNumRows = nMatrixRows;
    2628          25 :     nNumCols = nMatrixCols;
    2629          25 : }
    2630             : 
    2631             : 
    2632           2 : SmNode * SmMatrixNode::GetLeftMost()
    2633             : {
    2634           2 :     return this;
    2635             : }
    2636             : 
    2637             : 
    2638             : /**************************************************************************/
    2639             : 
    2640             : 
    2641        2766 : SmMathSymbolNode::SmMathSymbolNode(const SmToken &rNodeToken)
    2642        2766 : :   SmSpecialNode(NMATH, rNodeToken, FNT_MATH)
    2643             : {
    2644        2766 :     sal_Unicode cChar = GetToken().cMathChar;
    2645        2766 :     if ((sal_Unicode) '\0' != cChar)
    2646        2740 :         SetText(OUString(cChar));
    2647        2766 : }
    2648             : 
    2649         144 : void SmMathSymbolNode::AdaptToX(const OutputDevice &rDev, sal_uLong nWidth)
    2650             : {
    2651             :     // Since there is no function to do this, we try to approximate it:
    2652         144 :     Size  aFntSize (GetFont().GetSize());
    2653             : 
    2654             :     //! however the result is a bit better with 'nWidth' as initial font width
    2655         144 :     aFntSize.Width() = nWidth;
    2656         144 :     GetFont().SetSize(aFntSize);
    2657             : 
    2658         144 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    2659         144 :     aTmpDev.SetFont(GetFont());
    2660             : 
    2661             :     // get denominator of error factor for width
    2662         144 :     long nTmpBorderWidth = GetFont().GetBorderWidth();
    2663         144 :     long nDenom = SmRect(aTmpDev, NULL, GetText(), nTmpBorderWidth).GetItalicWidth();
    2664             : 
    2665             :     // scale fontwidth with this error factor
    2666         144 :     aFntSize.Width() *= nWidth;
    2667         144 :     aFntSize.Width() /= nDenom ? nDenom : 1;
    2668             : 
    2669         144 :     GetFont().SetSize(aFntSize);
    2670         144 : }
    2671             : 
    2672         950 : void SmMathSymbolNode::AdaptToY(const OutputDevice &rDev, sal_uLong nHeight)
    2673             : {
    2674         950 :     GetFont().FreezeBorderWidth();
    2675         950 :     Size  aFntSize (GetFont().GetSize());
    2676             : 
    2677             :     // Since we only want to scale the height, we might have
    2678             :     // to determine the font width in order to keep it
    2679         950 :     if (aFntSize.Width() == 0)
    2680             :     {
    2681         204 :         OutputDevice &rDevNC = (OutputDevice &) rDev;
    2682         204 :         rDevNC.Push(PushFlags::FONT | PushFlags::MAPMODE);
    2683         204 :         rDevNC.SetFont(GetFont());
    2684         204 :         aFntSize.Width() = rDev.GetFontMetric().GetSize().Width();
    2685         204 :         rDevNC.Pop();
    2686             :     }
    2687             :     OSL_ENSURE(aFntSize.Width() != 0, "Sm: ");
    2688             : 
    2689             :     //! however the result is a bit better with 'nHeight' as initial
    2690             :     //! font height
    2691         950 :     aFntSize.Height() = nHeight;
    2692         950 :     GetFont().SetSize(aFntSize);
    2693             : 
    2694         950 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    2695         950 :     aTmpDev.SetFont(GetFont());
    2696             : 
    2697             :     // get denominator of error factor for height
    2698         950 :     long nTmpBorderWidth = GetFont().GetBorderWidth();
    2699         950 :     long nDenom = SmRect(aTmpDev, NULL, GetText(), nTmpBorderWidth).GetHeight();
    2700             : 
    2701             :     // scale fontwidth with this error factor
    2702         950 :     aFntSize.Height() *= nHeight;
    2703         950 :     aFntSize.Height() /= nDenom ? nDenom : 1;
    2704             : 
    2705         950 :     GetFont().SetSize(aFntSize);
    2706         950 : }
    2707             : 
    2708             : 
    2709        2868 : void SmMathSymbolNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
    2710             : {
    2711        2868 :     SmNode::Prepare(rFormat, rDocShell);
    2712             : 
    2713        2868 :     GetFont() = rFormat.GetFont(GetFontDesc());
    2714             :     // use same font size as is used for variables
    2715        2868 :     GetFont().SetSize( rFormat.GetFont( FNT_VARIABLE ).GetSize() );
    2716             : 
    2717             :     OSL_ENSURE(GetFont().GetCharSet() == RTL_TEXTENCODING_SYMBOL  ||
    2718             :                GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE,
    2719             :         "wrong charset for character from StarMath/OpenSymbol font");
    2720             : 
    2721        2868 :     Flags() |= FLG_FONT | FLG_ITALIC;
    2722        2868 : };
    2723             : 
    2724             : 
    2725        2429 : void SmMathSymbolNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    2726             : {
    2727        2429 :     const OUString &rText = GetText();
    2728             : 
    2729        2429 :     if (rText.isEmpty() || rText[0] == '\0')
    2730          24 :     {   SmRect::operator = (SmRect());
    2731        2453 :         return;
    2732             :     }
    2733             : 
    2734        2405 :     PrepareAttributes();
    2735             : 
    2736        2405 :     GetFont() *= Fraction (rFormat.GetRelSize(SIZ_TEXT), 100);
    2737             : 
    2738        2405 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    2739        2405 :     aTmpDev.SetFont(GetFont());
    2740             : 
    2741        2405 :     SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth()));
    2742             : }
    2743             : 
    2744           6 : void SmMathSymbolNode::CreateTextFromNode(OUString &rText)
    2745             : {
    2746           6 :     OUString sStr;
    2747           6 :     MathType::LookupChar(GetToken().cMathChar, sStr);
    2748           6 :     rText += sStr;
    2749           6 : }
    2750             : 
    2751           0 : void SmRectangleNode::CreateTextFromNode(OUString &rText)
    2752             : {
    2753           0 :     switch (GetToken().eType)
    2754             :     {
    2755             :     case TUNDERLINE:
    2756           0 :         rText += "underline ";
    2757           0 :         break;
    2758             :     case TOVERLINE:
    2759           0 :         rText += "overline ";
    2760           0 :         break;
    2761             :     case TOVERSTRIKE:
    2762           0 :         rText += "overstrike ";
    2763           0 :         break;
    2764             :     default:
    2765           0 :         break;
    2766             :     }
    2767           0 : }
    2768             : 
    2769           0 : void SmAttributNode::CreateTextFromNode(OUString &rText)
    2770             : {
    2771             :     SmNode *pNode;
    2772           0 :     sal_uInt16  nSize = GetNumSubNodes();
    2773             :     OSL_ENSURE(nSize == 2, "Node missing members");
    2774           0 :     rText += "{";
    2775           0 :     sal_Unicode nLast=0;
    2776           0 :     if (NULL != (pNode = GetSubNode(0)))
    2777             :     {
    2778           0 :         OUString aStr;
    2779           0 :         pNode->CreateTextFromNode(aStr);
    2780           0 :         if (aStr.getLength() > 1)
    2781           0 :             rText += aStr;
    2782             :         else
    2783             :         {
    2784           0 :             nLast = aStr[0];
    2785           0 :             switch (nLast)
    2786             :             {
    2787             :             case MS_BAR: // MACRON
    2788           0 :                 rText += "overline ";
    2789           0 :                 break;
    2790             :             case MS_DOT: // DOT ABOVE
    2791           0 :                 rText += "dot ";
    2792           0 :                 break;
    2793             :             case 0x2dc: // SMALL TILDE
    2794           0 :                 rText += "widetilde ";
    2795           0 :                 break;
    2796             :             case MS_DDOT: // DIAERESIS
    2797           0 :                 rText += "ddot ";
    2798           0 :                 break;
    2799             :             case 0xE082:
    2800           0 :                 break;
    2801             :             case 0xE09B:
    2802             :             case MS_DDDOT: // COMBINING THREE DOTS ABOVE
    2803           0 :                 rText += "dddot ";
    2804           0 :                 break;
    2805             :             case MS_ACUTE: // ACUTE ACCENT
    2806             :             case MS_COMBACUTE: // COMBINING ACUTE ACCENT
    2807           0 :                 rText += "acute ";
    2808           0 :                 break;
    2809             :             case MS_GRAVE: // GRAVE ACCENT
    2810             :             case MS_COMBGRAVE: // COMBINING GRAVE ACCENT
    2811           0 :                 rText += "grave ";
    2812           0 :                 break;
    2813             :             case MS_CHECK: // CARON
    2814             :             case MS_COMBCHECK: // COMBINING CARON
    2815           0 :                 rText += "check ";
    2816           0 :                 break;
    2817             :             case MS_BREVE: // BREVE
    2818             :             case MS_COMBBREVE: // COMBINING BREVE
    2819           0 :                 rText += "breve ";
    2820           0 :                 break;
    2821             :             case MS_CIRCLE: // RING ABOVE
    2822             :             case MS_COMBCIRCLE: // COMBINING RING ABOVE
    2823           0 :                 rText += "circle ";
    2824           0 :                 break;
    2825             :             case MS_RIGHTARROW: // RIGHTWARDS ARROW
    2826             :             case MS_VEC: // COMBINING RIGHT ARROW ABOVE
    2827           0 :                 rText += "vec ";
    2828           0 :                 break;
    2829             :             case MS_TILDE: // TILDE
    2830             :             case MS_COMBTILDE: // COMBINING TILDE
    2831           0 :                 rText += "tilde ";
    2832           0 :                 break;
    2833             :             case MS_HAT: // CIRCUMFLEX ACCENT
    2834             :             case MS_COMBHAT: // COMBINING CIRCUMFLEX ACCENT
    2835           0 :                 rText += "hat ";
    2836           0 :                 break;
    2837             :             case MS_COMBBAR: // COMBINING MACRON
    2838           0 :                 rText += "bar ";
    2839           0 :                 break;
    2840             :             default:
    2841           0 :                 rText += OUString( nLast );
    2842           0 :                 break;
    2843             :             }
    2844           0 :         }
    2845             :     }
    2846             : 
    2847           0 :     if (nSize == 2)
    2848           0 :         if (NULL != (pNode = GetSubNode(1)))
    2849           0 :             pNode->CreateTextFromNode(rText);
    2850             : 
    2851           0 :     rText = comphelper::string::stripEnd(rText, ' ');
    2852             : 
    2853           0 :     if (nLast == 0xE082)
    2854           0 :         rText += " overbrace {}";
    2855             : 
    2856           0 :     rText += "} ";
    2857           0 : }
    2858             : 
    2859             : /**************************************************************************/
    2860             : 
    2861        3692 : static bool lcl_IsFromGreekSymbolSet( const OUString &rTokenText )
    2862             : {
    2863        3692 :     bool bRes = false;
    2864             : 
    2865             :     // valid symbol name needs to have a '%' at pos 0 and at least an additional char
    2866        3692 :     if (rTokenText.getLength() > 2 && rTokenText[0] == (sal_Unicode)'%')
    2867             :     {
    2868         131 :         OUString aName( rTokenText.copy(1) );
    2869         131 :         SmSym *pSymbol = SM_MOD()->GetSymbolManager().GetSymbolByName( aName );
    2870         131 :         if (pSymbol && GetExportSymbolSetName(pSymbol->GetSymbolSetName()) == "Greek")
    2871         106 :             bRes = true;
    2872             :     }
    2873             : 
    2874        3692 :     return bRes;
    2875             : }
    2876             : 
    2877             : 
    2878        3561 : SmSpecialNode::SmSpecialNode(SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 _nFontDesc) :
    2879        3561 :     SmTextNode(eNodeType, rNodeToken, _nFontDesc)
    2880             : {
    2881        3561 :     bIsFromGreekSymbolSet = lcl_IsFromGreekSymbolSet( rNodeToken.aText );
    2882        3561 : }
    2883             : 
    2884             : 
    2885         131 : SmSpecialNode::SmSpecialNode(const SmToken &rNodeToken) :
    2886         131 :     SmTextNode(NSPECIAL, rNodeToken, FNT_MATH)  // default Font isn't always correct!
    2887             : {
    2888         131 :     bIsFromGreekSymbolSet = lcl_IsFromGreekSymbolSet( rNodeToken.aText );
    2889         131 : }
    2890             : 
    2891             : 
    2892         131 : void SmSpecialNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
    2893             : {
    2894         131 :     SmNode::Prepare(rFormat, rDocShell);
    2895             : 
    2896             :     const SmSym   *pSym;
    2897         131 :     SmModule  *pp = SM_MOD();
    2898             : 
    2899         131 :     OUString aName(GetToken().aText.copy(1));
    2900         131 :     if (NULL != (pSym = pp->GetSymbolManager().GetSymbolByName( aName )))
    2901             :     {
    2902         130 :         sal_UCS4 cChar = pSym->GetCharacter();
    2903         130 :         OUString aTmp( &cChar, 1 );
    2904         130 :         SetText( aTmp );
    2905         130 :         GetFont() = pSym->GetFace();
    2906             :     }
    2907             :     else
    2908             :     {
    2909           1 :         SetText( GetToken().aText );
    2910           1 :         GetFont() = rFormat.GetFont(FNT_VARIABLE);
    2911             :     }
    2912             :     // use same font size as is used for variables
    2913         131 :     GetFont().SetSize( rFormat.GetFont( FNT_VARIABLE ).GetSize() );
    2914             : 
    2915             :     // Actually only WEIGHT_NORMAL and WEIGHT_BOLD should occur... However, the sms-file also
    2916             :     // contains e.g. 'WEIGHT_ULTRALIGHT'. Consequently, compare here with '>' instead of '!='.
    2917             :     // (In the long term the necessity for 'PrepareAttribut' and thus also for this here should be dropped)
    2918             : 
    2919             :     //! see also SmFontStyles::GetStyleName
    2920         131 :     if (IsItalic( GetFont() ))
    2921           1 :         SetAttribut(ATTR_ITALIC);
    2922         131 :     if (IsBold( GetFont() ))
    2923           0 :         SetAttribut(ATTR_BOLD);
    2924             : 
    2925         131 :     Flags() |= FLG_FONT;
    2926             : 
    2927         131 :     if (bIsFromGreekSymbolSet)
    2928             :     {
    2929             :         OSL_ENSURE( GetText().getLength() == 1, "a symbol should only consist of 1 char!" );
    2930         106 :         bool bItalic = false;
    2931         106 :         sal_Int16 nStyle = rFormat.GetGreekCharStyle();
    2932             :         OSL_ENSURE( nStyle >= 0 && nStyle <= 2, "unexpected value for GreekCharStyle" );
    2933         106 :         if (nStyle == 1)
    2934           0 :             bItalic = true;
    2935         106 :         else if (nStyle == 2)
    2936             :         {
    2937           0 :             const OUString& rTmp(GetText());
    2938           0 :             if (rTmp.isEmpty())
    2939             :             {
    2940             :                 static const sal_Unicode cUppercaseAlpha = 0x0391;
    2941             :                 static const sal_Unicode cUppercaseOmega = 0x03A9;
    2942           0 :                 sal_Unicode cChar = rTmp[0];
    2943             :                 // uppercase letters should be straight and lowercase letters italic
    2944           0 :                 bItalic = !(cUppercaseAlpha <= cChar && cChar <= cUppercaseOmega);
    2945             :             }
    2946             :         }
    2947             : 
    2948         106 :         if (bItalic)
    2949           0 :             Attributes() |= ATTR_ITALIC;
    2950             :         else
    2951         106 :             Attributes() &= ~ATTR_ITALIC;
    2952         131 :     }
    2953         131 : };
    2954             : 
    2955             : 
    2956           0 : void SmSpecialNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    2957             : {
    2958           0 :     PrepareAttributes();
    2959             : 
    2960           0 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    2961           0 :     aTmpDev.SetFont(GetFont());
    2962             : 
    2963           0 :     SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth()));
    2964           0 : }
    2965             : 
    2966             : /**************************************************************************/
    2967             : 
    2968             : 
    2969           0 : void SmGlyphSpecialNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    2970             : {
    2971           0 :     PrepareAttributes();
    2972             : 
    2973           0 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    2974           0 :     aTmpDev.SetFont(GetFont());
    2975             : 
    2976           0 :     SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(),
    2977           0 :                                GetFont().GetBorderWidth()).AsGlyphRect());
    2978           0 : }
    2979             : 
    2980             : 
    2981             : /**************************************************************************/
    2982             : 
    2983             : 
    2984         654 : void SmPlaceNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
    2985             : {
    2986         654 :     SmNode::Prepare(rFormat, rDocShell);
    2987             : 
    2988         654 :     GetFont().SetColor(COL_GRAY);
    2989         654 :     Flags() |= FLG_COLOR | FLG_FONT | FLG_ITALIC;
    2990         654 : };
    2991             : 
    2992             : 
    2993         654 : void SmPlaceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    2994             : {
    2995         654 :     PrepareAttributes();
    2996             : 
    2997         654 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    2998         654 :     aTmpDev.SetFont(GetFont());
    2999             : 
    3000         654 :     SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth()));
    3001         654 : }
    3002             : 
    3003             : 
    3004             : /**************************************************************************/
    3005             : 
    3006             : 
    3007          27 : void SmErrorNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
    3008             : {
    3009          27 :     SmNode::Prepare(rFormat, rDocShell);
    3010             : 
    3011          27 :     GetFont().SetColor(COL_RED);
    3012          27 :     Flags() |= FLG_VISIBLE | FLG_BOLD | FLG_ITALIC
    3013          27 :                | FLG_COLOR | FLG_FONT | FLG_SIZE;
    3014          27 : }
    3015             : 
    3016             : 
    3017          27 : void SmErrorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    3018             : {
    3019          27 :     PrepareAttributes();
    3020             : 
    3021          27 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    3022          27 :     aTmpDev.SetFont(GetFont());
    3023             : 
    3024          27 :     const OUString &rText = GetText();
    3025          27 :     SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth()));
    3026          27 : }
    3027             : 
    3028             : 
    3029             : /**************************************************************************/
    3030             : 
    3031             : 
    3032           4 : void SmBlankNode::IncreaseBy(const SmToken &rToken)
    3033             : {
    3034           4 :     switch(rToken.eType)
    3035             :     {
    3036           2 :         case TBLANK:    nNum += 4;  break;
    3037           2 :         case TSBLANK:   nNum += 1;  break;
    3038             :         default:
    3039           0 :             break;
    3040             :     }
    3041           4 : }
    3042             : 
    3043             : 
    3044           4 : void SmBlankNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
    3045             : {
    3046           4 :     SmNode::Prepare(rFormat, rDocShell);
    3047             : 
    3048             :     // Here it need/should not be the StarMath font, so that for the character
    3049             :     // used in Arrange a normal (non-clipped) rectangle is generated
    3050           4 :     GetFont() = rFormat.GetFont(FNT_VARIABLE);
    3051             : 
    3052           4 :     Flags() |= FLG_FONT | FLG_BOLD | FLG_ITALIC;
    3053           4 : }
    3054             : 
    3055             : 
    3056           0 : void SmBlankNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
    3057             : {
    3058           0 :     SmTmpDevice aTmpDev ((OutputDevice &) rDev, true);
    3059           0 :     aTmpDev.SetFont(GetFont());
    3060             : 
    3061             :     // make distance depend on the font height
    3062             :     // (so that it increases when scaling (e.g. size *2 {a ~ b})
    3063           0 :     long  nDist  = GetFont().GetSize().Height() / 10L,
    3064           0 :           nSpace = nNum * nDist;
    3065             : 
    3066             :     // get a SmRect with Baseline and all the bells and whistles
    3067             :     SmRect::operator = (SmRect(aTmpDev, &rFormat, OUString(' '),
    3068           0 :                                GetFont().GetBorderWidth()));
    3069             : 
    3070             :     // and resize it to the requested size
    3071           0 :     SetItalicSpaces(0, 0);
    3072           0 :     SetWidth(nSpace);
    3073           0 : }
    3074             : 
    3075             : /**************************************************************************/
    3076             : //Implementation of all accept methods for SmVisitor
    3077             : 
    3078           0 : void SmNode::Accept(SmVisitor*){
    3079             :     //This method is only implemented to avoid making SmNode abstract because an
    3080             :     //obscure copy constructor is used... I can't find it's implementation, and
    3081             :     //don't want to figure out how to fix it... If you want to, just delete this
    3082             :     //method, making SmNode abstract, and see where you can an problem with that.
    3083             :     SAL_WARN("starmath", "SmNode should not be visitable!");
    3084           0 : }
    3085             : 
    3086        5156 : void SmTableNode::Accept(SmVisitor* pVisitor) {
    3087        5156 :     pVisitor->Visit(this);
    3088        5156 : }
    3089             : 
    3090        2650 : void SmBraceNode::Accept(SmVisitor* pVisitor) {
    3091        2650 :     pVisitor->Visit(this);
    3092        2650 : }
    3093             : 
    3094        2642 : void SmBracebodyNode::Accept(SmVisitor* pVisitor) {
    3095        2642 :     pVisitor->Visit(this);
    3096        2642 : }
    3097             : 
    3098         960 : void SmOperNode::Accept(SmVisitor* pVisitor) {
    3099         960 :     pVisitor->Visit(this);
    3100         960 : }
    3101             : 
    3102          28 : void SmAlignNode::Accept(SmVisitor* pVisitor) {
    3103          28 :     pVisitor->Visit(this);
    3104          28 : }
    3105             : 
    3106        1503 : void SmAttributNode::Accept(SmVisitor* pVisitor) {
    3107        1503 :     pVisitor->Visit(this);
    3108        1503 : }
    3109             : 
    3110          84 : void SmFontNode::Accept(SmVisitor* pVisitor) {
    3111          84 :     pVisitor->Visit(this);
    3112          84 : }
    3113             : 
    3114         553 : void SmUnHorNode::Accept(SmVisitor* pVisitor) {
    3115         553 :     pVisitor->Visit(this);
    3116         553 : }
    3117             : 
    3118        4207 : void SmBinHorNode::Accept(SmVisitor* pVisitor) {
    3119        4207 :     pVisitor->Visit(this);
    3120        4207 : }
    3121             : 
    3122        1308 : void SmBinVerNode::Accept(SmVisitor* pVisitor) {
    3123        1308 :     pVisitor->Visit(this);
    3124        1308 : }
    3125             : 
    3126          64 : void SmBinDiagonalNode::Accept(SmVisitor* pVisitor) {
    3127          64 :     pVisitor->Visit(this);
    3128          64 : }
    3129             : 
    3130        4043 : void SmSubSupNode::Accept(SmVisitor* pVisitor) {
    3131        4043 :     pVisitor->Visit(this);
    3132        4043 : }
    3133             : 
    3134         110 : void SmMatrixNode::Accept(SmVisitor* pVisitor) {
    3135         110 :     pVisitor->Visit(this);
    3136         110 : }
    3137             : 
    3138        1576 : void SmPlaceNode::Accept(SmVisitor* pVisitor) {
    3139        1576 :     pVisitor->Visit(this);
    3140        1576 : }
    3141             : 
    3142       24476 : void SmTextNode::Accept(SmVisitor* pVisitor) {
    3143       24476 :     pVisitor->Visit(this);
    3144       24476 : }
    3145             : 
    3146         262 : void SmSpecialNode::Accept(SmVisitor* pVisitor) {
    3147         262 :     pVisitor->Visit(this);
    3148         262 : }
    3149             : 
    3150           0 : void SmGlyphSpecialNode::Accept(SmVisitor* pVisitor) {
    3151           0 :     pVisitor->Visit(this);
    3152           0 : }
    3153             : 
    3154       13005 : void SmMathSymbolNode::Accept(SmVisitor* pVisitor) {
    3155       13005 :     pVisitor->Visit(this);
    3156       13005 : }
    3157             : 
    3158           8 : void SmBlankNode::Accept(SmVisitor* pVisitor) {
    3159           8 :     pVisitor->Visit(this);
    3160           8 : }
    3161             : 
    3162         148 : void SmErrorNode::Accept(SmVisitor* pVisitor) {
    3163         148 :     pVisitor->Visit(this);
    3164         148 : }
    3165             : 
    3166        4593 : void SmLineNode::Accept(SmVisitor* pVisitor) {
    3167        4593 :     pVisitor->Visit(this);
    3168        4593 : }
    3169             : 
    3170        3760 : void SmExpressionNode::Accept(SmVisitor* pVisitor) {
    3171        3760 :     pVisitor->Visit(this);
    3172        3760 : }
    3173             : 
    3174          64 : void SmPolyLineNode::Accept(SmVisitor* pVisitor) {
    3175          64 :     pVisitor->Visit(this);
    3176          64 : }
    3177             : 
    3178         450 : void SmRootNode::Accept(SmVisitor* pVisitor) {
    3179         450 :     pVisitor->Visit(this);
    3180         450 : }
    3181             : 
    3182         446 : void SmRootSymbolNode::Accept(SmVisitor* pVisitor) {
    3183         446 :     pVisitor->Visit(this);
    3184         446 : }
    3185             : 
    3186           0 : void SmDynIntegralNode::Accept(SmVisitor* pVisitor) {
    3187           0 :     pVisitor->Visit(this);
    3188           0 : }
    3189             : 
    3190             : 
    3191           0 : void SmDynIntegralSymbolNode::Accept(SmVisitor* pVisitor) {
    3192           0 :     pVisitor->Visit(this);
    3193           0 : }
    3194             : 
    3195        1483 : void SmRectangleNode::Accept(SmVisitor* pVisitor) {
    3196        1483 :     pVisitor->Visit(this);
    3197        1483 : }
    3198             : 
    3199         212 : void SmVerticalBraceNode::Accept(SmVisitor* pVisitor) {
    3200         212 :     pVisitor->Visit(this);
    3201         254 : }
    3202             : 
    3203             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11