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