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