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

Generated by: LCOV version 1.10