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

Generated by: LCOV version 1.10