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

Generated by: LCOV version 1.10