1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
25 #include "document.hxx"
27 #include "mathtype.hxx"
28 #include "visitors.hxx"
30 #include <comphelper/string.hxx>
31 #include <tools/gen.hxx>
32 #include <tools/fract.hxx>
33 #include <rtl/math.hxx>
34 #include <tools/color.hxx>
35 #include <vcl/metric.hxx>
36 #include <vcl/lineinfo.hxx>
37 #include <vcl/outdev.hxx>
38 #include <sfx2/module.hxx>
44 ////////////////////////////////////////
46 // Allows for font and color changes. The original settings will be restored
48 // It's main purpose is to allow for the "const" in the 'OutputDevice'
49 // argument in the 'Arrange' functions and restore changes made in the 'Draw'
51 // Usually a MapMode of 1/100th mm will be used.
56 OutputDevice
&rOutDev
;
58 // disallow use of copy-constructor and assignment-operator
59 SmTmpDevice(const SmTmpDevice
&rTmpDev
);
60 SmTmpDevice
& operator = (const SmTmpDevice
&rTmpDev
);
62 Color
Impl_GetColor( const Color
& rColor
);
65 SmTmpDevice(OutputDevice
&rTheDev
, bool bUseMap100th_mm
);
66 ~SmTmpDevice() { rOutDev
.Pop(); }
68 void SetFont(const Font
&rNewFont
);
70 void SetLineColor( const Color
& rColor
) { rOutDev
.SetLineColor( Impl_GetColor(rColor
) ); }
71 void SetFillColor( const Color
& rColor
) { rOutDev
.SetFillColor( Impl_GetColor(rColor
) ); }
72 void SetTextColor( const Color
& rColor
) { rOutDev
.SetTextColor( Impl_GetColor(rColor
) ); }
74 operator OutputDevice
& () { return rOutDev
; }
78 SmTmpDevice::SmTmpDevice(OutputDevice
&rTheDev
, bool bUseMap100th_mm
) :
81 rOutDev
.Push( PUSH_FONT
| PUSH_MAPMODE
|
82 PUSH_LINECOLOR
| PUSH_FILLCOLOR
| PUSH_TEXTCOLOR
);
83 if (bUseMap100th_mm
&& MAP_100TH_MM
!= rOutDev
.GetMapMode().GetMapUnit())
85 OSL_FAIL( "incorrect MapMode?" );
86 rOutDev
.SetMapMode( MAP_100TH_MM
); //Immer fuer 100% fomatieren
91 Color
SmTmpDevice::Impl_GetColor( const Color
& rColor
)
93 ColorData nNewCol
= rColor
.GetColor();
94 if (COL_AUTO
== nNewCol
)
96 if (OUTDEV_PRINTER
== rOutDev
.GetOutDevType())
100 Color
aBgCol( rOutDev
.GetBackground().GetColor() );
101 if (OUTDEV_WINDOW
== rOutDev
.GetOutDevType())
102 aBgCol
= ((Window
&) rOutDev
).GetDisplayBackground().GetColor();
104 nNewCol
= SM_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
;
106 Color
aTmpColor( nNewCol
);
107 if (aBgCol
.IsDark() && aTmpColor
.IsDark())
109 else if (aBgCol
.IsBright() && aTmpColor
.IsBright())
113 return Color( nNewCol
);
117 void SmTmpDevice::SetFont(const Font
&rNewFont
)
119 rOutDev
.SetFont( rNewFont
);
120 rOutDev
.SetTextColor( Impl_GetColor( rNewFont
.GetColor() ) );
124 ///////////////////////////////////////////////////////////////////////////
127 SmNode::SmNode(SmNodeType eNodeType
, const SmToken
&rNodeToken
)
130 eScaleMode
= SCALE_NONE
;
131 aNodeToken
= rNodeToken
;
143 bool SmNode::IsVisible() const
149 sal_uInt16
SmNode::GetNumSubNodes() const
155 SmNode
* SmNode::GetSubNode(sal_uInt16
/*nIndex*/)
161 SmNode
* SmNode::GetLeftMost()
162 // returns leftmost node of current subtree.
163 //! (this assumes the one with index 0 is always the leftmost subnode
164 //! for the current node).
166 SmNode
*pNode
= GetNumSubNodes() > 0 ?
167 GetSubNode(0) : NULL
;
169 return pNode
? pNode
->GetLeftMost() : this;
173 void SmNode::SetPhantom(bool bIsPhantomP
)
175 if (! (Flags() & FLG_VISIBLE
))
176 bIsPhantom
= bIsPhantomP
;
179 sal_uInt16 nSize
= GetNumSubNodes();
180 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
181 if (NULL
!= (pNode
= GetSubNode(i
)))
182 pNode
->SetPhantom(bIsPhantom
);
186 void SmNode::SetColor(const Color
& rColor
)
188 if (! (Flags() & FLG_COLOR
))
189 GetFont().SetColor(rColor
);
192 sal_uInt16 nSize
= GetNumSubNodes();
193 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
194 if (NULL
!= (pNode
= GetSubNode(i
)))
195 pNode
->SetColor(rColor
);
199 void SmNode::SetAttribut(sal_uInt16 nAttrib
)
202 (nAttrib
== ATTR_BOLD
&& !(Flags() & FLG_BOLD
)) ||
203 (nAttrib
== ATTR_ITALIC
&& !(Flags() & FLG_ITALIC
))
206 nAttributes
|= nAttrib
;
210 sal_uInt16 nSize
= GetNumSubNodes();
211 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
212 if (NULL
!= (pNode
= GetSubNode(i
)))
213 pNode
->SetAttribut(nAttrib
);
217 void SmNode::ClearAttribut(sal_uInt16 nAttrib
)
220 (nAttrib
== ATTR_BOLD
&& !(Flags() & FLG_BOLD
)) ||
221 (nAttrib
== ATTR_ITALIC
&& !(Flags() & FLG_ITALIC
))
224 nAttributes
&= ~nAttrib
;
228 sal_uInt16 nSize
= GetNumSubNodes();
229 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
230 if (NULL
!= (pNode
= GetSubNode(i
)))
231 pNode
->ClearAttribut(nAttrib
);
235 void SmNode::SetFont(const SmFace
&rFace
)
237 if (!(Flags() & FLG_FONT
))
241 sal_uInt16 nSize
= GetNumSubNodes();
242 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
243 if (NULL
!= (pNode
= GetSubNode(i
)))
244 pNode
->SetFont(rFace
);
248 void SmNode::SetFontSize(const Fraction
&rSize
, sal_uInt16 nType
)
249 //! 'rSize' is in units of pts
253 if (!(Flags() & FLG_SIZE
))
255 Fraction
aVal (SmPtsTo100th_mm(rSize
.GetNumerator()),
256 rSize
.GetDenominator());
257 long nHeight
= (long)aVal
;
259 aFntSize
= GetFont().GetSize();
260 aFntSize
.Width() = 0;
264 aFntSize
.Height() = nHeight
;
268 aFntSize
.Height() += nHeight
;
272 aFntSize
.Height() -= nHeight
;
275 case FNTSIZ_MULTIPLY
:
276 aFntSize
.Height() = (long) (Fraction(aFntSize
.Height()) * rSize
);
280 if (rSize
!= Fraction(0L))
281 aFntSize
.Height() = (long) (Fraction(aFntSize
.Height()) / rSize
);
287 // check the requested size against maximum value
288 static int const nMaxVal
= SmPtsTo100th_mm(128);
289 if (aFntSize
.Height() > nMaxVal
)
290 aFntSize
.Height() = nMaxVal
;
292 GetFont().SetSize(aFntSize
);
296 sal_uInt16 nSize
= GetNumSubNodes();
297 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
298 if (NULL
!= (pNode
= GetSubNode(i
)))
299 pNode
->SetFontSize(rSize
, nType
);
303 void SmNode::SetSize(const Fraction
&rSize
)
308 sal_uInt16 nSize
= GetNumSubNodes();
309 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
310 if (NULL
!= (pNode
= GetSubNode(i
)))
311 pNode
->SetSize(rSize
);
315 void SmNode::SetRectHorAlign(RectHorAlign eHorAlign
, bool bApplyToSubTree
)
317 if (!(Flags() & FLG_HORALIGN
))
318 eRectHorAlign
= eHorAlign
;
323 sal_uInt16 nSize
= GetNumSubNodes();
324 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
325 if (NULL
!= (pNode
= GetSubNode(i
)))
326 pNode
->SetRectHorAlign(eHorAlign
);
331 void SmNode::PrepareAttributes()
333 GetFont().SetWeight((Attributes() & ATTR_BOLD
) ? WEIGHT_BOLD
: WEIGHT_NORMAL
);
334 GetFont().SetItalic((Attributes() & ATTR_ITALIC
) ? ITALIC_NORMAL
: ITALIC_NONE
);
338 void SmNode::Prepare(const SmFormat
&rFormat
, const SmDocShell
&rDocShell
)
340 #if OSL_DEBUG_LEVEL > 1
349 switch (rFormat
.GetHorAlign())
350 { case AlignLeft
: eRectHorAlign
= RHA_LEFT
; break;
351 case AlignCenter
: eRectHorAlign
= RHA_CENTER
; break;
352 case AlignRight
: eRectHorAlign
= RHA_RIGHT
; break;
355 GetFont() = rFormat
.GetFont(FNT_MATH
);
356 OSL_ENSURE( GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE
,
357 "unexpected CharSet" );
358 GetFont().SetWeight(WEIGHT_NORMAL
);
359 GetFont().SetItalic(ITALIC_NONE
);
362 sal_uInt16 nSize
= GetNumSubNodes();
363 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
364 if (NULL
!= (pNode
= GetSubNode(i
)))
365 pNode
->Prepare(rFormat
, rDocShell
);
368 sal_uInt16
SmNode::FindIndex() const
370 const SmStructureNode
* pParent
= GetParent();
371 if (!pParent
) { return 0; }
373 for (sal_uInt16 i
= 0; i
< pParent
->GetNumSubNodes(); ++i
) {
374 if (pParent
->GetSubNode(i
) == this) {
379 DBG_ASSERT(false, "Connection between parent and child is inconsistent.");
384 #if OSL_DEBUG_LEVEL > 1
385 void SmNode::ToggleDebug() const
386 // toggle 'bIsDebug' in current subtree
388 SmNode
*pThis
= (SmNode
*) this;
390 pThis
->bIsDebug
= bIsDebug
? false : true;
393 sal_uInt16 nSize
= GetNumSubNodes();
394 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
395 if (NULL
!= (pNode
= pThis
->GetSubNode(i
)))
396 pNode
->ToggleDebug();
401 void SmNode::Move(const Point
& rPosition
)
403 if (rPosition
.X() == 0 && rPosition
.Y() == 0)
406 SmRect::Move(rPosition
);
409 sal_uInt16 nSize
= GetNumSubNodes();
410 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
411 if (NULL
!= (pNode
= GetSubNode(i
)))
412 pNode
->Move(rPosition
);
416 void SmNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
419 sal_uInt16 nSize
= GetNumSubNodes();
420 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
421 if (NULL
!= (pNode
= GetSubNode(i
)))
422 pNode
->Arrange(rDev
, rFormat
);
425 void SmNode::CreateTextFromNode(String
&rText
)
428 sal_uInt16 nSize
= GetNumSubNodes();
431 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
432 if (NULL
!= (pNode
= GetSubNode(i
)))
433 pNode
->CreateTextFromNode(rText
);
436 rText
= comphelper::string::stripEnd(rText
, ' ');
442 void SmNode::AdaptToX(const OutputDevice
&/*rDev*/, sal_uLong
/*nWidth*/)
447 void SmNode::AdaptToY(const OutputDevice
&/*rDev*/, sal_uLong
/*nHeight*/)
452 const SmNode
* SmNode::FindTokenAt(sal_uInt16 nRow
, sal_uInt16 nCol
) const
453 // returns (first) ** visible ** (sub)node with the tokens text at
454 // position 'nRow', 'nCol'.
455 //! (there should be exactly one such node if any)
458 && nRow
== GetToken().nRow
459 && nCol
>= GetToken().nCol
&& nCol
< GetToken().nCol
+ GetToken().aText
.getLength())
463 sal_uInt16 nNumSubNodes
= GetNumSubNodes();
464 for (sal_uInt16 i
= 0; i
< nNumSubNodes
; i
++)
465 { const SmNode
*pNode
= GetSubNode(i
);
470 const SmNode
*pResult
= pNode
->FindTokenAt(nRow
, nCol
);
480 const SmNode
* SmNode::FindRectClosestTo(const Point
&rPoint
) const
482 long nDist
= LONG_MAX
;
483 const SmNode
*pResult
= 0;
489 sal_uInt16 nNumSubNodes
= GetNumSubNodes();
490 for (sal_uInt16 i
= 0; i
< nNumSubNodes
; i
++)
491 { const SmNode
*pNode
= GetSubNode(i
);
497 const SmNode
*pFound
= pNode
->FindRectClosestTo(rPoint
);
498 if (pFound
&& (nTmp
= pFound
->OrientedDist(rPoint
)) < nDist
)
502 // quit immediately if 'rPoint' is inside the *should not
503 // overlap with other rectangles* part.
504 // This (partly) serves for getting the attributes in eg
505 // "bar overstrike a".
506 // ('nDist < 0' is used as *quick shot* to avoid evaluation of
507 // the following expression, where the result is already determined)
508 if (nDist
< 0 && pFound
->IsInsideRect(rPoint
))
517 void SmNode::GetAccessibleText( OUStringBuffer
&/*rText*/ ) const
519 OSL_FAIL( "SmNode: GetAccessibleText not overloaded" );
522 const SmNode
* SmNode::FindNodeWithAccessibleIndex(xub_StrLen nAccIdx
) const
524 const SmNode
*pResult
= 0;
526 sal_Int32 nIdx
= GetAccessibleIndex();
529 GetAccessibleText( aTxt
); // get text if used in following 'if' statement
532 && nIdx
<= nAccIdx
&& nAccIdx
< nIdx
+ aTxt
.getLength())
536 sal_uInt16 nNumSubNodes
= GetNumSubNodes();
537 for (sal_uInt16 i
= 0; i
< nNumSubNodes
; i
++)
539 const SmNode
*pNode
= GetSubNode(i
);
543 pResult
= pNode
->FindNodeWithAccessibleIndex(nAccIdx
);
552 #ifdef DEBUG_ENABLE_DUMPASDOT
553 void SmNode::DumpAsDot(std::ostream
&out
, OUString
* label
, int number
, int& id
, int parent
) const
555 //If this is the root start the file
557 out
<<"digraph {"<<std::endl
;
559 out
<<"labelloc = \"t\";"<<std::endl
;
561 //CreateTextFromNode(eq);
562 eq
= eq
.replaceAll("\n", " ");
563 eq
= eq
.replaceAll("\\", "\\\\");
564 eq
= eq
.replaceAll("\"", "\\\"");
565 out
<<"label= \"Equation: \\\"";
566 out
<< OUStringToOString(eq
, RTL_TEXTENCODING_UTF8
).getStr();
567 out
<<"\\\"\";"<<std::endl
;
571 //Some how out<<(int)this; doesn't work... So we do this nasty workaround...
573 sprintf(strid
, "%i", id
);
576 sprintf(strnr
, "%i", number
);
578 //Dump connection to this node
581 sprintf(pid
, "%i", parent
);
582 out
<<"n"<<pid
<<" -> n"<<strid
<<" [label=\""<<strnr
<<"\"];"<<std::endl
;
583 //If doesn't have parent and isn't a rootnode:
584 } else if(number
!= -1) {
585 out
<<"orphaned -> n"<<strid
<<" [label=\""<<strnr
<<"\"];"<<std::endl
;
589 out
<<"n"<< strid
<<" [label=\"";
590 switch( GetType() ) {
591 case NTABLE
: out
<<"SmTableNode"; break;
592 case NBRACE
: out
<<"SmBraceNode"; break;
593 case NBRACEBODY
: out
<<"SmBracebodyNode"; break;
594 case NOPER
: out
<<"SmOperNode"; break;
595 case NALIGN
: out
<<"SmAlignNode"; break;
596 case NATTRIBUT
: out
<<"SmAttributNode"; break;
597 case NFONT
: out
<<"SmFontNode"; break;
598 case NUNHOR
: out
<<"SmUnHorNode"; break;
599 case NBINHOR
: out
<<"SmBinHorNode"; break;
600 case NBINVER
: out
<<"SmBinVerNode"; break;
601 case NBINDIAGONAL
: out
<<"SmBinDiagonalNode"; break;
602 case NSUBSUP
: out
<<"SmSubSupNode"; break;
603 case NMATRIX
: out
<<"SmMatrixNode"; break;
604 case NPLACE
: out
<<"SmPlaceNode"; break;
607 out
<< OUStringToOString(((SmTextNode
*)this)->GetText(), RTL_TEXTENCODING_UTF8
).getStr();
609 case NSPECIAL
: out
<<"SmSpecialNode"; break;
610 case NGLYPH_SPECIAL
: out
<<"SmGlyphSpecialNode"; break;
612 out
<<"SmMathSymbolNode: ";
613 out
<< OUStringToOString(((SmMathSymbolNode
*)this)->GetText(), RTL_TEXTENCODING_UTF8
).getStr();
615 case NBLANK
: out
<<"SmBlankNode"; break;
616 case NERROR
: out
<<"SmErrorNode"; break;
617 case NLINE
: out
<<"SmLineNode"; break;
618 case NEXPRESSION
: out
<<"SmExpressionNode"; break;
619 case NPOLYLINE
: out
<<"SmPolyLineNode"; break;
620 case NROOT
: out
<<"SmRootNode"; break;
621 case NROOTSYMBOL
: out
<<"SmRootSymbolNode"; break;
622 case NRECTANGLE
: out
<<"SmRectangleNode"; break;
623 case NVERTICAL_BRACE
: out
<<"SmVerticalBraceNode"; break;
629 out
<<", style=dashed";
630 out
<<"];"<<std::endl
;
635 sal_uInt16 nSize
= GetNumSubNodes();
636 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
637 if (NULL
!= (pNode
= GetSubNode(i
)))
638 pNode
->DumpAsDot(out
, NULL
, i
, ++id
, myid
);
640 //If this is the root end the file
644 #endif /* DEBUG_ENABLE_DUMPASDOT */
646 long SmNode::GetFormulaBaseline() const
648 OSL_FAIL( "This dummy implementation should not have been called." );
652 ///////////////////////////////////////////////////////////////////////////
654 SmStructureNode::SmStructureNode( const SmStructureNode
&rNode
) :
655 SmNode( rNode
.GetType(), rNode
.GetToken() )
658 for (i
= 0; i
< aSubNodes
.size(); i
++)
662 sal_uLong nSize
= rNode
.aSubNodes
.size();
663 aSubNodes
.resize( nSize
);
664 for (i
= 0; i
< nSize
; ++i
)
666 SmNode
*pNode
= rNode
.aSubNodes
[i
];
667 aSubNodes
[i
] = pNode
? new SmNode( *pNode
) : 0;
673 SmStructureNode::~SmStructureNode()
677 for (sal_uInt16 i
= 0; i
< GetNumSubNodes(); i
++)
678 if (NULL
!= (pNode
= GetSubNode(i
)))
683 SmStructureNode
& SmStructureNode::operator = ( const SmStructureNode
&rNode
)
685 SmNode::operator = ( rNode
);
688 for (i
= 0; i
< aSubNodes
.size(); i
++)
692 sal_uLong nSize
= rNode
.aSubNodes
.size();
693 aSubNodes
.resize( nSize
);
694 for (i
= 0; i
< nSize
; ++i
)
696 SmNode
*pNode
= rNode
.aSubNodes
[i
];
697 aSubNodes
[i
] = pNode
? new SmNode( *pNode
) : 0;
706 void SmStructureNode::SetSubNodes(SmNode
*pFirst
, SmNode
*pSecond
, SmNode
*pThird
)
708 size_t nSize
= pThird
? 3 : (pSecond
? 2 : (pFirst
? 1 : 0));
709 aSubNodes
.resize( nSize
);
711 aSubNodes
[0] = pFirst
;
713 aSubNodes
[1] = pSecond
;
715 aSubNodes
[2] = pThird
;
721 void SmStructureNode::SetSubNodes(const SmNodeArray
&rNodeArray
)
723 aSubNodes
= rNodeArray
;
728 bool SmStructureNode::IsVisible() const
734 sal_uInt16
SmStructureNode::GetNumSubNodes() const
736 return (sal_uInt16
) aSubNodes
.size();
740 SmNode
* SmStructureNode::GetSubNode(sal_uInt16 nIndex
)
742 return aSubNodes
[nIndex
];
746 void SmStructureNode::GetAccessibleText( OUStringBuffer
&rText
) const
748 sal_uInt16 nNodes
= GetNumSubNodes();
749 for (sal_uInt16 i
= 0; i
< nNodes
; ++i
)
751 const SmNode
*pNode
= ((SmStructureNode
*) this)->GetSubNode(i
);
754 if (pNode
->IsVisible())
755 ((SmStructureNode
*) pNode
)->nAccIndex
= rText
.getLength();
756 pNode
->GetAccessibleText( rText
);
761 ///////////////////////////////////////////////////////////////////////////
764 bool SmVisibleNode::IsVisible() const
770 sal_uInt16
SmVisibleNode::GetNumSubNodes() const
776 SmNode
* SmVisibleNode::GetSubNode(sal_uInt16
/*nIndex*/)
782 ///////////////////////////////////////////////////////////////////////////
784 void SmGraphicNode::GetAccessibleText( OUStringBuffer
&rText
) const
786 rText
.append(GetToken().aText
);
789 ///////////////////////////////////////////////////////////////////////////
792 void SmExpressionNode::CreateTextFromNode(String
&rText
)
795 sal_uInt16 nSize
= GetNumSubNodes();
798 for (sal_uInt16 i
= 0; i
< nSize
; i
++)
799 if (NULL
!= (pNode
= GetSubNode(i
)))
801 pNode
->CreateTextFromNode(rText
);
802 //Just a bit of foo to make unary +asd -asd +-asd -+asd look nice
803 if (pNode
->GetType() == NMATH
)
804 if ((nSize
!= 2) || ((rText
.GetChar(rText
.Len()-1) != '+') &&
805 (rText
.GetChar(rText
.Len()-1) != '-')))
811 rText
= comphelper::string::stripEnd(rText
, ' ');
817 ///////////////////////////////////////////////////////////////////////////
819 void SmTableNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
820 // arranges all subnodes in one column
823 sal_uInt16 nSize
= GetNumSubNodes();
825 // make distance depend on font size
826 long nDist
= +(rFormat
.GetDistance(DIS_VERTICAL
)
827 * GetFont().GetSize().Height()) / 100L;
832 // arrange subnodes and get maximum width of them
836 for (i
= 0; i
< nSize
; i
++)
837 if (NULL
!= (pNode
= GetSubNode(i
)))
838 { pNode
->Arrange(rDev
, rFormat
);
839 if ((nTmp
= pNode
->GetItalicWidth()) > nMaxWidth
)
844 SmRect::operator = (SmRect(nMaxWidth
, 1));
845 for (i
= 0; i
< nSize
; i
++)
846 { if (NULL
!= (pNode
= GetSubNode(i
)))
847 { const SmRect
&rNodeRect
= pNode
->GetRect();
848 const SmNode
*pCoNode
= pNode
->GetLeftMost();
849 RectHorAlign eHorAlign
= pCoNode
->GetRectHorAlign();
851 aPos
= rNodeRect
.AlignTo(*this, RP_BOTTOM
,
852 eHorAlign
, RVA_BASELINE
);
856 ExtendBy(rNodeRect
, nSize
> 1 ? RCP_NONE
: RCP_ARG
);
861 nFormulaBaseline
= GetBaseline();
864 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, sal_True
);
865 aTmpDev
.SetFont(GetFont());
867 SmRect aRect
= (SmRect(aTmpDev
, &rFormat
, OUString("a"),
868 GetFont().GetBorderWidth()));
869 nFormulaBaseline
= GetAlignM();
870 // move from middle position by constant - distance
871 // between middle and baseline for single letter
872 nFormulaBaseline
+= aRect
.GetBaseline() - aRect
.GetAlignM();
877 SmNode
* SmTableNode::GetLeftMost()
883 long SmTableNode::GetFormulaBaseline() const
885 return nFormulaBaseline
;
889 /**************************************************************************/
892 void SmLineNode::Prepare(const SmFormat
&rFormat
, const SmDocShell
&rDocShell
)
894 SmNode::Prepare(rFormat
, rDocShell
);
896 // Here we use the 'FNT_VARIABLE' font since it's ascent and descent in general fit better
897 // to the rest of the formula compared to the 'FNT_MATH' font.
898 GetFont() = rFormat
.GetFont(FNT_VARIABLE
);
903 /**************************************************************************/
906 void SmLineNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
907 // arranges all subnodes in one row with some extra space between
910 sal_uInt16 nSize
= GetNumSubNodes();
912 for (i
= 0; i
< nSize
; i
++)
913 if (NULL
!= (pNode
= GetSubNode(i
)))
914 pNode
->Arrange(rDev
, rFormat
);
916 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
917 aTmpDev
.SetFont(GetFont());
921 // provide an empty rectangle with alignment parameters for the "current"
922 // font (in order to make "a^1 {}_2^3 a_4" work correct, that is, have the
923 // same sub-/supscript positions.)
924 //! be sure to use a character that has explicitly defined HiAttribut
925 //! line in rect.cxx such as 'a' in order to make 'vec a' look same to
927 SmRect::operator = (SmRect(aTmpDev
, &rFormat
, OUString("a"),
928 GetFont().GetBorderWidth()));
929 // make sure that the rectangle occupies (almost) no space
931 SetItalicSpaces(0, 0);
935 // make distance depend on font size
936 long nDist
= (rFormat
.GetDistance(DIS_HORIZONTAL
) * GetFont().GetSize().Height()) / 100L;
937 if (!IsUseExtraSpaces())
941 // copy the first node into LineNode and extend by the others
942 if (NULL
!= (pNode
= GetSubNode(0)))
943 SmRect::operator = (pNode
->GetRect());
945 for (i
= 1; i
< nSize
; i
++)
946 if (NULL
!= (pNode
= GetSubNode(i
)))
948 aPos
= pNode
->AlignTo(*this, RP_RIGHT
, RHA_CENTER
, RVA_BASELINE
);
950 // add horizontal space to the left for each but the first sub node
954 ExtendBy( *pNode
, RCP_XOR
);
959 /**************************************************************************/
962 void SmExpressionNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
963 // as 'SmLineNode::Arrange' but keeps alignment of leftmost subnode
965 SmLineNode::Arrange(rDev
, rFormat
);
967 // copy alignment of leftmost subnode if any
968 SmNode
*pNode
= GetLeftMost();
970 SetRectHorAlign(pNode
->GetRectHorAlign(), false);
974 /**************************************************************************/
977 void SmUnHorNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
979 bool bIsPostfix
= GetToken().eType
== TFACT
;
981 SmNode
*pOper
= GetSubNode(bIsPostfix
? 1 : 0),
982 *pBody
= GetSubNode(bIsPostfix
? 0 : 1);
983 OSL_ENSURE(pOper
, "Sm: NULL pointer");
984 OSL_ENSURE(pBody
, "Sm: NULL pointer");
986 pOper
->SetSize(Fraction (rFormat
.GetRelSize(SIZ_OPERATOR
), 100));
987 pOper
->Arrange(rDev
, rFormat
);
988 pBody
->Arrange(rDev
, rFormat
);
990 Point aPos
= pOper
->AlignTo(*pBody
, bIsPostfix
? RP_RIGHT
: RP_LEFT
,
991 RHA_CENTER
, RVA_BASELINE
);
992 // add a bit space between operator and argument
993 // (worst case -{1 over 2} where - and over have almost no space inbetween)
994 long nDelta
= pOper
->GetFont().GetSize().Height() / 20;
1001 SmRect::operator = (*pBody
);
1002 long nOldBot
= GetBottom();
1004 ExtendBy(*pOper
, RCP_XOR
);
1006 // workaround for Bug 50865: "a^2 a^+2" have different baselines
1007 // for exponents (if size of exponent is large enough)
1012 /**************************************************************************/
1015 void SmRootNode::GetHeightVerOffset(const SmRect
&rRect
,
1016 long &rHeight
, long &rVerOffset
) const
1017 // calculate height and vertical offset of root sign suitable for 'rRect'
1019 rVerOffset
= (rRect
.GetBottom() - rRect
.GetAlignB()) / 2;
1020 rHeight
= rRect
.GetHeight() - rVerOffset
;
1022 OSL_ENSURE(rHeight
>= 0, "Sm : Ooops...");
1023 OSL_ENSURE(rVerOffset
>= 0, "Sm : Ooops...");
1027 Point
SmRootNode::GetExtraPos(const SmRect
&rRootSymbol
,
1028 const SmRect
&rExtra
) const
1030 const Size
&rSymSize
= rRootSymbol
.GetSize();
1032 Point aPos
= rRootSymbol
.GetTopLeft()
1033 + Point((rSymSize
.Width() * 70) / 100,
1034 (rSymSize
.Height() * 52) / 100);
1036 // from this calculate topleft edge of 'rExtra'
1037 aPos
.X() -= rExtra
.GetWidth() + rExtra
.GetItalicRightSpace();
1038 aPos
.Y() -= rExtra
.GetHeight();
1039 // if there's enough space move a bit less to the right
1040 // examples: "nroot i a", "nroot j a"
1041 // (it looks better if we don't use italic-spaces here)
1042 long nX
= rRootSymbol
.GetLeft() + (rSymSize
.Width() * 30) / 100;
1050 void SmRootNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1052 //! pExtra needs to have the smaller index than pRootSym in order to
1053 //! not to get the root symbol but the pExtra when clicking on it in the
1054 //! GraphicWindow. (That is because of the simplicity of the algorithm
1055 //! that finds the node corresponding to a mouseclick in the window.)
1056 SmNode
*pExtra
= GetSubNode(0),
1057 *pRootSym
= GetSubNode(1),
1058 *pBody
= GetSubNode(2);
1059 OSL_ENSURE(pRootSym
, "Sm: NULL pointer");
1060 OSL_ENSURE(pBody
, "Sm: NULL pointer");
1062 pBody
->Arrange(rDev
, rFormat
);
1066 GetHeightVerOffset(*pBody
, nHeight
, nVerOffset
);
1067 nHeight
+= rFormat
.GetDistance(DIS_ROOT
)
1068 * GetFont().GetSize().Height() / 100L;
1070 // font specialist advised to change the width first
1071 pRootSym
->AdaptToY(rDev
, nHeight
);
1072 pRootSym
->AdaptToX(rDev
, pBody
->GetItalicWidth());
1074 pRootSym
->Arrange(rDev
, rFormat
);
1076 Point aPos
= pRootSym
->AlignTo(*pBody
, RP_LEFT
, RHA_CENTER
, RVA_BASELINE
);
1077 //! overrride calculated vertical position
1078 aPos
.Y() = pRootSym
->GetTop() + pBody
->GetBottom() - pRootSym
->GetBottom();
1079 aPos
.Y() -= nVerOffset
;
1080 pRootSym
->MoveTo(aPos
);
1083 { pExtra
->SetSize(Fraction(rFormat
.GetRelSize(SIZ_INDEX
), 100));
1084 pExtra
->Arrange(rDev
, rFormat
);
1086 aPos
= GetExtraPos(*pRootSym
, *pExtra
);
1087 pExtra
->MoveTo(aPos
);
1090 SmRect::operator = (*pBody
);
1091 ExtendBy(*pRootSym
, RCP_THIS
);
1093 ExtendBy(*pExtra
, RCP_THIS
, true);
1097 void SmRootNode::CreateTextFromNode(String
&rText
)
1099 SmNode
*pExtra
= GetSubNode(0);
1103 pExtra
->CreateTextFromNode(rText
);
1107 GetSubNode(2)->CreateTextFromNode(rText
);
1111 /**************************************************************************/
1114 void SmBinHorNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1116 SmNode
*pLeft
= GetSubNode(0),
1117 *pOper
= GetSubNode(1),
1118 *pRight
= GetSubNode(2);
1119 OSL_ENSURE(pLeft
!= NULL
, "Sm: NULL pointer");
1120 OSL_ENSURE(pOper
!= NULL
, "Sm: NULL pointer");
1121 OSL_ENSURE(pRight
!= NULL
, "Sm: NULL pointer");
1123 pOper
->SetSize(Fraction (rFormat
.GetRelSize(SIZ_OPERATOR
), 100));
1125 pLeft
->Arrange(rDev
, rFormat
);
1126 pOper
->Arrange(rDev
, rFormat
);
1127 pRight
->Arrange(rDev
, rFormat
);
1129 const SmRect
&rOpRect
= pOper
->GetRect();
1131 long nDist
= (rOpRect
.GetWidth() *
1132 rFormat
.GetDistance(DIS_HORIZONTAL
)) / 100L;
1134 SmRect::operator = (*pLeft
);
1137 aPos
= pOper
->AlignTo(*this, RP_RIGHT
, RHA_CENTER
, RVA_BASELINE
);
1139 pOper
->MoveTo(aPos
);
1140 ExtendBy(*pOper
, RCP_XOR
);
1142 aPos
= pRight
->AlignTo(*this, RP_RIGHT
, RHA_CENTER
, RVA_BASELINE
);
1145 pRight
->MoveTo(aPos
);
1146 ExtendBy(*pRight
, RCP_XOR
);
1150 /**************************************************************************/
1153 void SmBinVerNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1155 SmNode
*pNum
= GetSubNode(0),
1156 *pLine
= GetSubNode(1),
1157 *pDenom
= GetSubNode(2);
1158 OSL_ENSURE(pNum
, "Sm : NULL pointer");
1159 OSL_ENSURE(pLine
, "Sm : NULL pointer");
1160 OSL_ENSURE(pDenom
, "Sm : NULL pointer");
1162 bool bIsTextmode
= rFormat
.IsTextmode();
1165 Fraction
aFraction(rFormat
.GetRelSize(SIZ_INDEX
), 100);
1166 pNum
->SetSize(aFraction
);
1167 pLine
->SetSize(aFraction
);
1168 pDenom
->SetSize(aFraction
);
1171 pNum
->Arrange(rDev
, rFormat
);
1172 pDenom
->Arrange(rDev
, rFormat
);
1174 long nFontHeight
= GetFont().GetSize().Height(),
1175 nExtLen
= nFontHeight
* rFormat
.GetDistance(DIS_FRACTION
) / 100L,
1176 nThick
= nFontHeight
* rFormat
.GetDistance(DIS_STROKEWIDTH
) / 100L,
1177 nWidth
= std::max(pNum
->GetItalicWidth(), pDenom
->GetItalicWidth()),
1178 nNumDist
= bIsTextmode
? 0 :
1179 nFontHeight
* rFormat
.GetDistance(DIS_NUMERATOR
) / 100L,
1180 nDenomDist
= bIsTextmode
? 0 :
1181 nFontHeight
* rFormat
.GetDistance(DIS_DENOMINATOR
) / 100L;
1183 // font specialist advised to change the width first
1184 pLine
->AdaptToY(rDev
, nThick
);
1185 pLine
->AdaptToX(rDev
, nWidth
+ 2 * nExtLen
);
1186 pLine
->Arrange(rDev
, rFormat
);
1188 // get horizontal alignment for numerator
1189 const SmNode
*pLM
= pNum
->GetLeftMost();
1190 RectHorAlign eHorAlign
= pLM
->GetRectHorAlign();
1192 // move numerator to its position
1193 Point aPos
= pNum
->AlignTo(*pLine
, RP_TOP
, eHorAlign
, RVA_BASELINE
);
1194 aPos
.Y() -= nNumDist
;
1197 // get horizontal alignment for denominator
1198 pLM
= pDenom
->GetLeftMost();
1199 eHorAlign
= pLM
->GetRectHorAlign();
1201 // move denominator to its position
1202 aPos
= pDenom
->AlignTo(*pLine
, RP_BOTTOM
, eHorAlign
, RVA_BASELINE
);
1203 aPos
.Y() += nDenomDist
;
1204 pDenom
->MoveTo(aPos
);
1206 SmRect::operator = (*pNum
);
1207 ExtendBy(*pDenom
, RCP_NONE
).ExtendBy(*pLine
, RCP_NONE
, pLine
->GetCenterY());
1210 void SmBinVerNode::CreateTextFromNode(String
&rText
)
1212 SmNode
*pNum
= GetSubNode(0),
1213 *pDenom
= GetSubNode(2);
1214 pNum
->CreateTextFromNode(rText
);
1216 pDenom
->CreateTextFromNode(rText
);
1220 SmNode
* SmBinVerNode::GetLeftMost()
1226 /**************************************************************************/
1229 /// @return value of the determinant formed by the two points
1230 double Det(const Point
&rHeading1
, const Point
&rHeading2
)
1232 return rHeading1
.X() * rHeading2
.Y() - rHeading1
.Y() * rHeading2
.X();
1236 /// Is true iff the point 'rPoint1' belongs to the straight line through 'rPoint2'
1237 /// and has the direction vector 'rHeading2'
1238 bool IsPointInLine(const Point
&rPoint1
,
1239 const Point
&rPoint2
, const Point
&rHeading2
)
1241 OSL_ENSURE(rHeading2
!= Point(), "Sm : 0 vector");
1244 const double eps
= 5.0 * DBL_EPSILON
;
1247 if (labs(rHeading2
.X()) > labs(rHeading2
.Y()))
1249 fLambda
= (rPoint1
.X() - rPoint2
.X()) / (double) rHeading2
.X();
1250 bRes
= fabs(rPoint1
.Y() - (rPoint2
.Y() + fLambda
* rHeading2
.Y())) < eps
;
1254 fLambda
= (rPoint1
.Y() - rPoint2
.Y()) / (double) rHeading2
.Y();
1255 bRes
= fabs(rPoint1
.X() - (rPoint2
.X() + fLambda
* rHeading2
.X())) < eps
;
1262 sal_uInt16
GetLineIntersectionPoint(Point
&rResult
,
1263 const Point
& rPoint1
, const Point
&rHeading1
,
1264 const Point
& rPoint2
, const Point
&rHeading2
)
1266 OSL_ENSURE(rHeading1
!= Point(), "Sm : 0 vector");
1267 OSL_ENSURE(rHeading2
!= Point(), "Sm : 0 vector");
1269 sal_uInt16 nRes
= 1;
1270 const double eps
= 5.0 * DBL_EPSILON
;
1272 // are the direction vectors linearly dependent?
1273 double fDet
= Det(rHeading1
, rHeading2
);
1274 if (fabs(fDet
) < eps
)
1276 nRes
= IsPointInLine(rPoint1
, rPoint2
, rHeading2
) ? USHRT_MAX
: 0;
1277 rResult
= nRes
? rPoint1
: Point();
1281 // here we do not pay attention to the computational accurancy
1282 // (that would be more complicated and is not really worth it in this case)
1283 double fLambda
= ( (rPoint1
.Y() - rPoint2
.Y()) * rHeading2
.X()
1284 - (rPoint1
.X() - rPoint2
.X()) * rHeading2
.Y())
1286 rResult
= Point(rPoint1
.X() + (long) (fLambda
* rHeading1
.X()),
1287 rPoint1
.Y() + (long) (fLambda
* rHeading1
.Y()));
1295 SmBinDiagonalNode::SmBinDiagonalNode(const SmToken
&rNodeToken
)
1296 : SmStructureNode(NBINDIAGONAL
, rNodeToken
)
1303 /// @return position and size of the diagonal line
1304 /// premise: SmRect of the node defines the limitation(!) consequently it has to be known upfront
1305 void SmBinDiagonalNode::GetOperPosSize(Point
&rPos
, Size
&rSize
,
1306 const Point
&rDiagPoint
, double fAngleDeg
) const
1309 const double fPi
= 3.1415926535897932384626433;
1310 double fAngleRad
= fAngleDeg
/ 180.0 * fPi
;
1311 long nRectLeft
= GetItalicLeft(),
1312 nRectRight
= GetItalicRight(),
1313 nRectTop
= GetTop(),
1314 nRectBottom
= GetBottom();
1315 Point
aRightHdg (100, 0),
1317 aDiagHdg ( (long)(100.0 * cos(fAngleRad
)),
1318 (long)(-100.0 * sin(fAngleRad
)) );
1320 long nLeft
, nRight
, nTop
, nBottom
; // margins of the rectangle for the diagonal
1324 // determine top right corner
1325 GetLineIntersectionPoint(aPoint
,
1326 Point(nRectLeft
, nRectTop
), aRightHdg
,
1327 rDiagPoint
, aDiagHdg
);
1328 // is there a point of intersection with the top border?
1329 if (aPoint
.X() <= nRectRight
)
1331 nRight
= aPoint
.X();
1336 // there has to be a point of intersection with the right border!
1337 GetLineIntersectionPoint(aPoint
,
1338 Point(nRectRight
, nRectTop
), aDownHdg
,
1339 rDiagPoint
, aDiagHdg
);
1341 nRight
= nRectRight
;
1345 // determine bottom left corner
1346 GetLineIntersectionPoint(aPoint
,
1347 Point(nRectLeft
, nRectBottom
), aRightHdg
,
1348 rDiagPoint
, aDiagHdg
);
1349 // is there a point of intersection with the bottom border?
1350 if (aPoint
.X() >= nRectLeft
)
1353 nBottom
= nRectBottom
;
1357 // there has to be a point of intersection with the left border!
1358 GetLineIntersectionPoint(aPoint
,
1359 Point(nRectLeft
, nRectTop
), aDownHdg
,
1360 rDiagPoint
, aDiagHdg
);
1363 nBottom
= aPoint
.Y();
1368 // determine top left corner
1369 GetLineIntersectionPoint(aPoint
,
1370 Point(nRectLeft
, nRectTop
), aRightHdg
,
1371 rDiagPoint
, aDiagHdg
);
1372 // is there a point of intersection with the top border?
1373 if (aPoint
.X() >= nRectLeft
)
1380 // there has to be a point of intersection with the left border!
1381 GetLineIntersectionPoint(aPoint
,
1382 Point(nRectLeft
, nRectTop
), aDownHdg
,
1383 rDiagPoint
, aDiagHdg
);
1389 // determine bottom right corner
1390 GetLineIntersectionPoint(aPoint
,
1391 Point(nRectLeft
, nRectBottom
), aRightHdg
,
1392 rDiagPoint
, aDiagHdg
);
1393 // is there a point of intersection with the bottom border?
1394 if (aPoint
.X() <= nRectRight
)
1396 nRight
= aPoint
.X();
1397 nBottom
= nRectBottom
;
1401 // there has to be a point of intersection with the right border!
1402 GetLineIntersectionPoint(aPoint
,
1403 Point(nRectRight
, nRectTop
), aDownHdg
,
1404 rDiagPoint
, aDiagHdg
);
1406 nRight
= nRectRight
;
1407 nBottom
= aPoint
.Y();
1411 rSize
= Size(nRight
- nLeft
+ 1, nBottom
- nTop
+ 1);
1417 void SmBinDiagonalNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1419 // Both arguments have to get into the SubNodes before the Operator so that clicking
1420 // within the GraphicWindow sets the FormulaCursor correctly (cf. SmRootNode)
1421 SmNode
*pLeft
= GetSubNode(0),
1422 *pRight
= GetSubNode(1);
1423 OSL_ENSURE(pLeft
, "Sm : NULL pointer");
1424 OSL_ENSURE(pRight
, "Sm : NULL pointer");
1426 OSL_ENSURE(GetSubNode(2)->GetType() == NPOLYLINE
, "Sm : wrong node type");
1427 SmPolyLineNode
*pOper
= (SmPolyLineNode
*) GetSubNode(2);
1428 OSL_ENSURE(pOper
, "Sm : NULL pointer");
1430 //! some routines being called extract some info from the OutputDevice's
1431 //! font (eg the space to be used for borders OR the font name(!!)).
1432 //! Thus the font should reflect the needs and has to be set!
1433 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
1434 aTmpDev
.SetFont(GetFont());
1436 pLeft
->Arrange(aTmpDev
, rFormat
);
1437 pRight
->Arrange(aTmpDev
, rFormat
);
1439 // determine implicitely the values (incl. the margin) of the diagonal line
1440 pOper
->Arrange(aTmpDev
, rFormat
);
1442 long nDelta
= pOper
->GetWidth() * 8 / 10;
1444 // determine TopLeft position from the right argument
1446 aPos
.X() = pLeft
->GetItalicRight() + nDelta
+ pRight
->GetItalicLeftSpace();
1448 aPos
.Y() = pLeft
->GetBottom() + nDelta
;
1450 aPos
.Y() = pLeft
->GetTop() - nDelta
- pRight
->GetHeight();
1452 pRight
->MoveTo(aPos
);
1454 // determine new baseline
1455 long nTmpBaseline
= IsAscending() ? (pLeft
->GetBottom() + pRight
->GetTop()) / 2
1456 : (pLeft
->GetTop() + pRight
->GetBottom()) / 2;
1457 Point
aLogCenter ((pLeft
->GetItalicRight() + pRight
->GetItalicLeft()) / 2,
1460 SmRect::operator = (*pLeft
);
1461 ExtendBy(*pRight
, RCP_NONE
);
1464 // determine position and size of diagonal line
1466 GetOperPosSize(aPos
, aTmpSize
, aLogCenter
, IsAscending() ? 60.0 : -60.0);
1468 // font specialist advised to change the width first
1469 pOper
->AdaptToY(aTmpDev
, aTmpSize
.Height());
1470 pOper
->AdaptToX(aTmpDev
, aTmpSize
.Width());
1471 // and make it active
1472 pOper
->Arrange(aTmpDev
, rFormat
);
1474 pOper
->MoveTo(aPos
);
1476 ExtendBy(*pOper
, RCP_NONE
, nTmpBaseline
);
1480 /**************************************************************************/
1483 void SmSubSupNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1485 OSL_ENSURE(GetNumSubNodes() == 1 + SUBSUP_NUM_ENTRIES
,
1486 "Sm: wrong number of subnodes");
1488 SmNode
*pBody
= GetBody();
1489 OSL_ENSURE(pBody
, "Sm: NULL pointer");
1491 long nOrigHeight
= pBody
->GetFont().GetSize().Height();
1493 pBody
->Arrange(rDev
, rFormat
);
1495 const SmRect
&rBodyRect
= pBody
->GetRect();
1496 SmRect::operator = (rBodyRect
);
1498 // line that separates sub- and supscript rectangles
1499 long nDelimLine
= SmFromTo(GetAlignB(), GetAlignT(), 0.4);
1504 // iterate over all possible sub-/supscripts
1505 SmRect
aTmpRect (rBodyRect
);
1506 for (int i
= 0; i
< SUBSUP_NUM_ENTRIES
; i
++)
1507 { SmSubSup eSubSup
= (SmSubSup
) i
; // cast
1508 SmNode
*pSubSup
= GetSubSup(eSubSup
);
1513 // switch position of limits if we are in textmode
1514 if (rFormat
.IsTextmode() && (GetToken().nGroup
& TGLIMIT
))
1516 { case CSUB
: eSubSup
= RSUB
; break;
1517 case CSUP
: eSubSup
= RSUP
; break;
1522 // prevent sub-/supscripts from diminishing in size
1523 // (as would be in "a_{1_{2_{3_4}}}")
1524 if (GetFont().GetSize().Height() > rFormat
.GetBaseSize().Height() / 3)
1526 sal_uInt16 nIndex
= (eSubSup
== CSUB
|| eSubSup
== CSUP
) ?
1527 SIZ_LIMITS
: SIZ_INDEX
;
1528 Fraction
aFraction ( rFormat
.GetRelSize(nIndex
), 100 );
1529 pSubSup
->SetSize(aFraction
);
1532 pSubSup
->Arrange(rDev
, rFormat
);
1534 bool bIsTextmode
= rFormat
.IsTextmode();
1537 //! be sure that CSUB, CSUP are handled before the other cases!
1543 * rFormat
.GetDistance(DIS_SUBSCRIPT
) / 100L;
1544 aPos
= pSubSup
->GetRect().AlignTo(aTmpRect
,
1545 eSubSup
== LSUB
? RP_LEFT
: RP_RIGHT
,
1546 RHA_CENTER
, RVA_BOTTOM
);
1548 nDelta
= nDelimLine
- aPos
.Y();
1556 * rFormat
.GetDistance(DIS_SUPERSCRIPT
) / 100L;
1557 aPos
= pSubSup
->GetRect().AlignTo(aTmpRect
,
1558 eSubSup
== LSUP
? RP_LEFT
: RP_RIGHT
,
1559 RHA_CENTER
, RVA_TOP
);
1561 nDelta
= aPos
.Y() + pSubSup
->GetHeight() - nDelimLine
;
1568 * rFormat
.GetDistance(DIS_LOWERLIMIT
) / 100L;
1569 aPos
= pSubSup
->GetRect().AlignTo(rBodyRect
, RP_BOTTOM
,
1570 RHA_CENTER
, RVA_BASELINE
);
1576 * rFormat
.GetDistance(DIS_UPPERLIMIT
) / 100L;
1577 aPos
= pSubSup
->GetRect().AlignTo(rBodyRect
, RP_TOP
,
1578 RHA_CENTER
, RVA_BASELINE
);
1582 OSL_FAIL("Sm: unknown case");
1586 pSubSup
->MoveTo(aPos
);
1587 ExtendBy(*pSubSup
, RCP_THIS
, true);
1589 // update rectangle to which RSUB, RSUP, LSUB, LSUP
1590 // will be aligned to
1591 if (eSubSup
== CSUB
|| eSubSup
== CSUP
)
1596 void SmSubSupNode::CreateTextFromNode(String
&rText
)
1599 GetSubNode(0)->CreateTextFromNode(rText
);
1601 if (NULL
!= (pNode
= GetSubNode(LSUB
+1)))
1604 pNode
->CreateTextFromNode(rText
);
1606 if (NULL
!= (pNode
= GetSubNode(LSUP
+1)))
1609 pNode
->CreateTextFromNode(rText
);
1611 if (NULL
!= (pNode
= GetSubNode(CSUB
+1)))
1614 pNode
->CreateTextFromNode(rText
);
1616 if (NULL
!= (pNode
= GetSubNode(CSUP
+1)))
1619 pNode
->CreateTextFromNode(rText
);
1621 if (NULL
!= (pNode
= GetSubNode(RSUB
+1)))
1623 rText
= comphelper::string::stripEnd(rText
, ' ');
1625 pNode
->CreateTextFromNode(rText
);
1627 if (NULL
!= (pNode
= GetSubNode(RSUP
+1)))
1629 rText
= comphelper::string::stripEnd(rText
, ' ');
1631 pNode
->CreateTextFromNode(rText
);
1636 /**************************************************************************/
1638 void SmBraceNode::CreateTextFromNode(String
&rText
)
1640 if (GetScaleMode() == SCALE_HEIGHT
)
1644 GetSubNode(0)->CreateTextFromNode(aStr
);
1645 aStr
= comphelper::string::strip(aStr
, ' ');
1646 aStr
= comphelper::string::stripStart(aStr
, '\\');
1649 if (aStr
.EqualsAscii("divides"))
1651 else if (aStr
.EqualsAscii("parallel"))
1653 else if (aStr
.EqualsAscii("<"))
1662 GetSubNode(1)->CreateTextFromNode(rText
);
1663 if (GetScaleMode() == SCALE_HEIGHT
)
1667 GetSubNode(2)->CreateTextFromNode(aStr
);
1668 aStr
= comphelper::string::strip(aStr
, ' ');
1669 aStr
= comphelper::string::stripStart(aStr
, '\\');
1672 if (aStr
.EqualsAscii("divides"))
1674 else if (aStr
.EqualsAscii("parallel"))
1676 else if (aStr
.EqualsAscii(">"))
1689 void SmBraceNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1691 SmNode
*pLeft
= GetSubNode(0),
1692 *pBody
= GetSubNode(1),
1693 *pRight
= GetSubNode(2);
1694 OSL_ENSURE(pLeft
, "Sm: NULL pointer");
1695 OSL_ENSURE(pBody
, "Sm: NULL pointer");
1696 OSL_ENSURE(pRight
, "Sm: NULL pointer");
1698 pBody
->Arrange(rDev
, rFormat
);
1700 bool bIsScaleNormal
= rFormat
.IsScaleNormalBrackets(),
1701 bScale
= pBody
->GetHeight() > 0 &&
1702 (GetScaleMode() == SCALE_HEIGHT
|| bIsScaleNormal
),
1703 bIsABS
= GetToken().eType
== TABS
;
1705 long nFaceHeight
= GetFont().GetSize().Height();
1707 // determine oversize in %
1708 sal_uInt16 nPerc
= 0;
1709 if (!bIsABS
&& bScale
)
1710 { // in case of oversize braces...
1711 sal_uInt16 nIndex
= GetScaleMode() == SCALE_HEIGHT
?
1712 DIS_BRACKETSIZE
: DIS_NORMALBRACKETSIZE
;
1713 nPerc
= rFormat
.GetDistance(nIndex
);
1716 // determine the height for the braces
1720 nBraceHeight
= pBody
->GetType() == NBRACEBODY
?
1721 ((SmBracebodyNode
*) pBody
)->GetBodyHeight()
1722 : pBody
->GetHeight();
1723 nBraceHeight
+= 2 * (nBraceHeight
* nPerc
/ 100L);
1726 nBraceHeight
= nFaceHeight
;
1728 // distance to the argument
1729 nPerc
= bIsABS
? 0 : rFormat
.GetDistance(DIS_BRACKETSPACE
);
1730 long nDist
= nFaceHeight
* nPerc
/ 100L;
1732 // if wanted, scale the braces to the wanted size
1735 Size
aTmpSize (pLeft
->GetFont().GetSize());
1736 OSL_ENSURE(pRight
->GetFont().GetSize() == aTmpSize
,
1737 "Sm : different font sizes");
1738 aTmpSize
.Width() = std::min((long) nBraceHeight
* 60L / 100L,
1739 rFormat
.GetBaseSize().Height() * 3L / 2L);
1740 // correction factor since change from StarMath to OpenSymbol font
1741 // because of the different font width in the FontMetric
1742 aTmpSize
.Width() *= 182;
1743 aTmpSize
.Width() /= 267;
1745 sal_Unicode cChar
= pLeft
->GetToken().cMathChar
;
1746 if (cChar
!= MS_LINE
&& cChar
!= MS_DLINE
)
1747 pLeft
->GetFont().SetSize(aTmpSize
);
1749 cChar
= pRight
->GetToken().cMathChar
;
1750 if (cChar
!= MS_LINE
&& cChar
!= MS_DLINE
)
1751 pRight
->GetFont().SetSize(aTmpSize
);
1753 pLeft
->AdaptToY(rDev
, nBraceHeight
);
1754 pRight
->AdaptToY(rDev
, nBraceHeight
);
1757 pLeft
->Arrange(rDev
, rFormat
);
1758 pRight
->Arrange(rDev
, rFormat
);
1760 // required in order to make "\(a\) - (a) - left ( a right )" look alright
1761 RectVerAlign eVerAlign
= bScale
? RVA_CENTERY
: RVA_BASELINE
;
1764 aPos
= pLeft
->AlignTo(*pBody
, RP_LEFT
, RHA_CENTER
, eVerAlign
);
1766 pLeft
->MoveTo(aPos
);
1768 aPos
= pRight
->AlignTo(*pBody
, RP_RIGHT
, RHA_CENTER
, eVerAlign
);
1770 pRight
->MoveTo(aPos
);
1772 SmRect::operator = (*pBody
);
1773 ExtendBy(*pLeft
, RCP_THIS
).ExtendBy(*pRight
, RCP_THIS
);
1777 /**************************************************************************/
1780 void SmBracebodyNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1782 sal_uInt16 nNumSubNodes
= GetNumSubNodes();
1783 if (nNumSubNodes
== 0)
1786 // arrange arguments
1788 for (i
= 0; i
< nNumSubNodes
; i
+= 2)
1789 GetSubNode(i
)->Arrange(rDev
, rFormat
);
1791 // build reference rectangle with necessary info for vertical alignment
1792 SmRect
aRefRect (*GetSubNode(0));
1793 for (i
= 0; i
< nNumSubNodes
; i
+= 2)
1795 SmRect
aTmpRect (*GetSubNode(i
));
1796 Point aPos
= aTmpRect
.AlignTo(aRefRect
, RP_RIGHT
, RHA_CENTER
, RVA_BASELINE
);
1797 aTmpRect
.MoveTo(aPos
);
1798 aRefRect
.ExtendBy(aTmpRect
, RCP_XOR
);
1801 nBodyHeight
= aRefRect
.GetHeight();
1803 // scale separators to required height and arrange them
1804 bool bScale
= GetScaleMode() == SCALE_HEIGHT
|| rFormat
.IsScaleNormalBrackets();
1805 long nHeight
= bScale
? aRefRect
.GetHeight() : GetFont().GetSize().Height();
1806 sal_uInt16 nIndex
= GetScaleMode() == SCALE_HEIGHT
?
1807 DIS_BRACKETSIZE
: DIS_NORMALBRACKETSIZE
;
1808 sal_uInt16 nPerc
= rFormat
.GetDistance(nIndex
);
1810 nHeight
+= 2 * (nHeight
* nPerc
/ 100L);
1811 for (i
= 1; i
< nNumSubNodes
; i
+= 2)
1813 SmNode
*pNode
= GetSubNode(i
);
1814 pNode
->AdaptToY(rDev
, nHeight
);
1815 pNode
->Arrange(rDev
, rFormat
);
1818 // horizontal distance between argument and brackets or separators
1819 long nDist
= GetFont().GetSize().Height()
1820 * rFormat
.GetDistance(DIS_BRACKETSPACE
) / 100L;
1822 SmNode
*pLeft
= GetSubNode(0);
1823 SmRect::operator = (*pLeft
);
1824 for (i
= 1; i
< nNumSubNodes
; i
++)
1826 bool bIsSeparator
= i
% 2 != 0;
1827 RectVerAlign eVerAlign
= bIsSeparator
? RVA_CENTERY
: RVA_BASELINE
;
1829 SmNode
*pRight
= GetSubNode(i
);
1830 Point aPosX
= pRight
->AlignTo(*pLeft
, RP_RIGHT
, RHA_CENTER
, eVerAlign
),
1831 aPosY
= pRight
->AlignTo(aRefRect
, RP_RIGHT
, RHA_CENTER
, eVerAlign
);
1834 pRight
->MoveTo(Point(aPosX
.X(), aPosY
.Y()));
1835 ExtendBy(*pRight
, bIsSeparator
? RCP_THIS
: RCP_XOR
);
1842 /**************************************************************************/
1845 void SmVerticalBraceNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1847 SmNode
*pBody
= GetSubNode(0),
1848 *pBrace
= GetSubNode(1),
1849 *pScript
= GetSubNode(2);
1850 OSL_ENSURE(pBody
, "Sm: NULL pointer!");
1851 OSL_ENSURE(pBrace
, "Sm: NULL pointer!");
1852 OSL_ENSURE(pScript
, "Sm: NULL pointer!");
1854 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
1855 aTmpDev
.SetFont(GetFont());
1857 pBody
->Arrange(aTmpDev
, rFormat
);
1859 // size is the same as for limits for this part
1860 pScript
->SetSize( Fraction( rFormat
.GetRelSize(SIZ_LIMITS
), 100 ) );
1861 // braces are a bit taller than usually
1862 pBrace
->SetSize( Fraction(3, 2) );
1864 long nItalicWidth
= pBody
->GetItalicWidth();
1865 if (nItalicWidth
> 0)
1866 pBrace
->AdaptToX(aTmpDev
, nItalicWidth
);
1868 pBrace
->Arrange(aTmpDev
, rFormat
);
1869 pScript
->Arrange(aTmpDev
, rFormat
);
1871 // determine the relative position and the distances between each other
1873 long nFontHeight
= pBody
->GetFont().GetSize().Height();
1874 long nDistBody
= nFontHeight
* rFormat
.GetDistance(DIS_ORNAMENTSIZE
),
1875 nDistScript
= nFontHeight
;
1876 if (GetToken().eType
== TOVERBRACE
)
1879 nDistBody
= - nDistBody
;
1880 nDistScript
*= - rFormat
.GetDistance(DIS_UPPERLIMIT
);
1884 eRectPos
= RP_BOTTOM
;
1885 nDistScript
*= + rFormat
.GetDistance(DIS_LOWERLIMIT
);
1888 nDistScript
/= 100L;
1890 Point aPos
= pBrace
->AlignTo(*pBody
, eRectPos
, RHA_CENTER
, RVA_BASELINE
);
1891 aPos
.Y() += nDistBody
;
1892 pBrace
->MoveTo(aPos
);
1894 aPos
= pScript
->AlignTo(*pBrace
, eRectPos
, RHA_CENTER
, RVA_BASELINE
);
1895 aPos
.Y() += nDistScript
;
1896 pScript
->MoveTo(aPos
);
1898 SmRect::operator = (*pBody
);
1899 ExtendBy(*pBrace
, RCP_THIS
).ExtendBy(*pScript
, RCP_THIS
);
1903 /**************************************************************************/
1906 SmNode
* SmOperNode::GetSymbol()
1908 SmNode
*pNode
= GetSubNode(0);
1909 OSL_ENSURE(pNode
, "Sm: NULL pointer!");
1911 if (pNode
->GetType() == NSUBSUP
)
1912 pNode
= ((SmSubSupNode
*) pNode
)->GetBody();
1914 OSL_ENSURE(pNode
, "Sm: NULL pointer!");
1919 long SmOperNode::CalcSymbolHeight(const SmNode
&rSymbol
,
1920 const SmFormat
&rFormat
) const
1921 // returns the font height to be used for operator-symbol
1923 long nHeight
= GetFont().GetSize().Height();
1925 SmTokenType eTmpType
= GetToken().eType
;
1926 if (eTmpType
== TLIM
|| eTmpType
== TLIMINF
|| eTmpType
== TLIMSUP
)
1929 if (!rFormat
.IsTextmode())
1931 // set minimum size ()
1932 nHeight
+= (nHeight
* 20L) / 100L;
1935 * rFormat
.GetDistance(DIS_OPERATORSIZE
) / 100L;
1936 nHeight
= nHeight
* 686L / 845L;
1939 // correct user-defined symbols to match height of sum from used font
1940 if (rSymbol
.GetToken().eType
== TSPECIAL
)
1941 nHeight
= nHeight
* 845L / 686L;
1947 void SmOperNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1949 SmNode
*pOper
= GetSubNode(0);
1950 SmNode
*pBody
= GetSubNode(1);
1952 OSL_ENSURE(pOper
, "Sm: missing subnode");
1953 OSL_ENSURE(pBody
, "Sm: missing subnode");
1955 SmNode
*pSymbol
= GetSymbol();
1956 pSymbol
->SetSize(Fraction(CalcSymbolHeight(*pSymbol
, rFormat
),
1957 pSymbol
->GetFont().GetSize().Height()));
1959 pBody
->Arrange(rDev
, rFormat
);
1960 pOper
->Arrange(rDev
, rFormat
);
1962 long nOrigHeight
= GetFont().GetSize().Height(),
1964 * rFormat
.GetDistance(DIS_OPERATORSPACE
) / 100L;
1966 Point aPos
= pOper
->AlignTo(*pBody
, RP_LEFT
, RHA_CENTER
, /*RVA_CENTERY*/RVA_MID
);
1968 pOper
->MoveTo(aPos
);
1970 SmRect::operator = (*pBody
);
1971 ExtendBy(*pOper
, RCP_THIS
);
1975 /**************************************************************************/
1978 void SmAlignNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
1979 // set alignment within the entire subtree (including current node)
1981 OSL_ENSURE(GetNumSubNodes() > 0, "Sm: missing subnode");
1983 SmNode
*pNode
= GetSubNode(0);
1985 RectHorAlign eHorAlign
= RHA_CENTER
;
1986 switch (GetToken().eType
)
1988 case TALIGNL
: eHorAlign
= RHA_LEFT
; break;
1989 case TALIGNC
: eHorAlign
= RHA_CENTER
; break;
1990 case TALIGNR
: eHorAlign
= RHA_RIGHT
; break;
1994 SetRectHorAlign(eHorAlign
);
1996 pNode
->Arrange(rDev
, rFormat
);
1998 SmRect::operator = (pNode
->GetRect());
2002 /**************************************************************************/
2005 void SmAttributNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
2007 SmNode
*pAttr
= GetSubNode(0),
2008 *pBody
= GetSubNode(1);
2009 OSL_ENSURE(pBody
, "Sm: body missing");
2010 OSL_ENSURE(pAttr
, "Sm: attribute missing");
2012 pBody
->Arrange(rDev
, rFormat
);
2014 if (GetScaleMode() == SCALE_WIDTH
)
2015 pAttr
->AdaptToX(rDev
, pBody
->GetItalicWidth());
2016 pAttr
->Arrange(rDev
, rFormat
);
2018 // get relative position of attribute
2019 RectVerAlign eVerAlign
;
2021 switch (GetToken().eType
)
2023 eVerAlign
= RVA_ATTRIBUT_LO
;
2026 eVerAlign
= RVA_ATTRIBUT_MID
;
2029 eVerAlign
= RVA_ATTRIBUT_HI
;
2030 if (pBody
->GetType() == NATTRIBUT
)
2031 nDist
= GetFont().GetSize().Height()
2032 * rFormat
.GetDistance(DIS_ORNAMENTSPACE
) / 100L;
2034 Point aPos
= pAttr
->AlignTo(*pBody
, RP_ATTRIBUT
, RHA_CENTER
, eVerAlign
);
2036 pAttr
->MoveTo(aPos
);
2038 SmRect::operator = (*pBody
);
2039 ExtendBy(*pAttr
, RCP_THIS
, true);
2043 /**************************************************************************/
2048 void SmFontNode::CreateTextFromNode(String
&rText
)
2050 switch (GetToken().eType
)
2062 rText
+= "nitalic ";
2065 rText
+= "phantom ";
2078 case FNTSIZ_MULTIPLY
:
2084 case FNTSIZ_ABSOLUT
:
2088 rText
+= String( ::rtl::math::doubleToUString(
2089 static_cast<double>(aFontSize
),
2090 rtl_math_StringFormat_Automatic
,
2091 rtl_math_DecimalPlaces_Max
, '.', sal_True
));
2096 rText
+= "color black ";
2099 rText
+= "color white ";
2102 rText
+= "color red ";
2105 rText
+= "color green ";
2108 rText
+= "color blue ";
2111 rText
+= "color cyan ";
2114 rText
+= "color magenta ";
2117 rText
+= "color yellow ";
2120 rText
+= "font sans ";
2123 rText
+= "font serif ";
2126 rText
+= "font fixed ";
2131 GetSubNode(1)->CreateTextFromNode(rText
);
2135 void SmFontNode::Prepare(const SmFormat
&rFormat
, const SmDocShell
&rDocShell
)
2137 //! prepare subnodes first
2138 SmNode::Prepare(rFormat
, rDocShell
);
2141 switch (GetToken().eType
)
2143 case TFIXED
: nFnt
= FNT_FIXED
; break;
2144 case TSANS
: nFnt
= FNT_SANS
; break;
2145 case TSERIF
: nFnt
= FNT_SERIF
; break;
2150 { GetFont() = rFormat
.GetFont( sal::static_int_cast
< sal_uInt16
>(nFnt
) );
2154 //! prevent overwrites of this font by 'Arrange' or 'SetFont' calls of
2155 //! other font nodes (those with lower depth in the tree)
2156 Flags() |= FLG_FONT
;
2160 void SmFontNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
2162 SmNode
*pNode
= GetSubNode(1);
2163 OSL_ENSURE(pNode
, "Sm: missing subnode");
2165 switch (GetToken().eType
)
2167 pNode
->SetFontSize(aFontSize
, nSizeType
);
2172 pNode
->SetFont(GetFont());
2174 case TUNKNOWN
: break; // no assertion on "font <?> <?>"
2176 case TPHANTOM
: SetPhantom(true); break;
2177 case TBOLD
: SetAttribut(ATTR_BOLD
); break;
2178 case TITALIC
: SetAttribut(ATTR_ITALIC
); break;
2179 case TNBOLD
: ClearAttribut(ATTR_BOLD
); break;
2180 case TNITALIC
: ClearAttribut(ATTR_ITALIC
); break;
2182 case TBLACK
: SetColor(Color(COL_BLACK
)); break;
2183 case TWHITE
: SetColor(Color(COL_WHITE
)); break;
2184 case TRED
: SetColor(Color(COL_RED
)); break;
2185 case TGREEN
: SetColor(Color(COL_GREEN
)); break;
2186 case TBLUE
: SetColor(Color(COL_BLUE
)); break;
2187 case TCYAN
: SetColor(Color(COL_CYAN
)); break;
2188 case TMAGENTA
: SetColor(Color(COL_MAGENTA
)); break;
2189 case TYELLOW
: SetColor(Color(COL_YELLOW
)); break;
2192 OSL_FAIL("Sm: unknown case");
2195 pNode
->Arrange(rDev
, rFormat
);
2197 SmRect::operator = (pNode
->GetRect());
2201 void SmFontNode::SetSizeParameter(const Fraction
& rValue
, sal_uInt16 Type
)
2208 /**************************************************************************/
2211 SmPolyLineNode::SmPolyLineNode(const SmToken
&rNodeToken
)
2212 : SmGraphicNode(NPOLYLINE
, rNodeToken
)
2219 void SmPolyLineNode::AdaptToX(const OutputDevice
&/*rDev*/, sal_uLong nNewWidth
)
2221 aToSize
.Width() = nNewWidth
;
2225 void SmPolyLineNode::AdaptToY(const OutputDevice
&/*rDev*/, sal_uLong nNewHeight
)
2227 GetFont().FreezeBorderWidth();
2228 aToSize
.Height() = nNewHeight
;
2232 void SmPolyLineNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
2234 //! some routines being called extract some info from the OutputDevice's
2235 //! font (eg the space to be used for borders OR the font name(!!)).
2236 //! Thus the font should reflect the needs and has to be set!
2237 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
2238 aTmpDev
.SetFont(GetFont());
2240 long nBorderwidth
= GetFont().GetBorderWidth();
2242 // create polygon using both endpoints
2243 OSL_ENSURE(aPoly
.GetSize() == 2, "Sm : wrong number of points");
2244 Point aPointA
, aPointB
;
2245 if (GetToken().eType
== TWIDESLASH
)
2247 aPointA
.X() = nBorderwidth
;
2248 aPointA
.Y() = aToSize
.Height() - nBorderwidth
;
2249 aPointB
.X() = aToSize
.Width() - nBorderwidth
;
2250 aPointB
.Y() = nBorderwidth
;
2254 OSL_ENSURE(GetToken().eType
== TWIDEBACKSLASH
, "Sm : unexpected token");
2256 aPointA
.Y() = nBorderwidth
;
2257 aPointB
.X() = aToSize
.Width() - nBorderwidth
;
2258 aPointB
.Y() = aToSize
.Height() - nBorderwidth
;
2260 aPoly
.SetPoint(aPointA
, 0);
2261 aPoly
.SetPoint(aPointB
, 1);
2263 long nThick
= GetFont().GetSize().Height()
2264 * rFormat
.GetDistance(DIS_STROKEWIDTH
) / 100L;
2265 nWidth
= nThick
+ 2 * nBorderwidth
;
2267 SmRect::operator = (SmRect(aToSize
.Width(), aToSize
.Height()));
2271 /**************************************************************************/
2273 void SmRootSymbolNode::AdaptToX(const OutputDevice
&/*rDev*/, sal_uLong nWidth
)
2275 nBodyWidth
= nWidth
;
2279 void SmRootSymbolNode::AdaptToY(const OutputDevice
&rDev
, sal_uLong nHeight
)
2281 // some additional length so that the horizontal
2282 // bar will be positioned above the argument
2283 SmMathSymbolNode::AdaptToY(rDev
, nHeight
+ nHeight
/ 10L);
2287 /**************************************************************************/
2290 void SmRectangleNode::AdaptToX(const OutputDevice
&/*rDev*/, sal_uLong nWidth
)
2292 aToSize
.Width() = nWidth
;
2296 void SmRectangleNode::AdaptToY(const OutputDevice
&/*rDev*/, sal_uLong nHeight
)
2298 GetFont().FreezeBorderWidth();
2299 aToSize
.Height() = nHeight
;
2303 void SmRectangleNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&/*rFormat*/)
2305 long nFontHeight
= GetFont().GetSize().Height();
2306 long nWidth
= aToSize
.Width(),
2307 nHeight
= aToSize
.Height();
2309 nHeight
= nFontHeight
/ 30;
2311 nWidth
= nFontHeight
/ 3;
2313 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
2314 aTmpDev
.SetFont(GetFont());
2316 // add some borderspace
2317 sal_uLong nTmpBorderWidth
= GetFont().GetBorderWidth();
2318 nHeight
+= 2 * nTmpBorderWidth
;
2320 //! use this method in order to have 'SmRect::HasAlignInfo() == true'
2321 //! and thus having the attribut-fences updated in 'SmRect::ExtendBy'
2322 SmRect::operator = (SmRect(nWidth
, nHeight
));
2326 /**************************************************************************/
2329 SmTextNode::SmTextNode( SmNodeType eNodeType
, const SmToken
&rNodeToken
, sal_uInt16 nFontDescP
) :
2330 SmVisibleNode(eNodeType
, rNodeToken
)
2332 nFontDesc
= nFontDescP
;
2336 SmTextNode::SmTextNode( const SmToken
&rNodeToken
, sal_uInt16 nFontDescP
) :
2337 SmVisibleNode(NTEXT
, rNodeToken
)
2339 nFontDesc
= nFontDescP
;
2343 void SmTextNode::Prepare(const SmFormat
&rFormat
, const SmDocShell
&rDocShell
)
2345 SmNode::Prepare(rFormat
, rDocShell
);
2347 // default setting for horizontal alignment of nodes with TTEXT
2348 // content is as alignl (cannot be done in Arrange since it would
2349 // override the settings made by an SmAlignNode before)
2350 if (TTEXT
== GetToken().eType
)
2351 SetRectHorAlign( RHA_LEFT
);
2353 aText
= GetToken().aText
;
2354 GetFont() = rFormat
.GetFont(GetFontDesc());
2356 if (IsItalic( GetFont() ))
2357 Attributes() |= ATTR_ITALIC
;
2358 if (IsBold( GetFont() ))
2359 Attributes() |= ATTR_BOLD
;
2361 // special handling for ':' where it is a token on it's own and is likely
2362 // to be used for mathematical notations. (E.g. a:b = 2:3)
2363 // In that case it should not be displayed in italic.
2364 if (GetToken().aText
.getLength() == 1 && GetToken().aText
[0] == ':')
2365 Attributes() &= ~ATTR_ITALIC
;
2369 void SmTextNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
2371 PrepareAttributes();
2373 sal_uInt16 nSizeDesc
= GetFontDesc() == FNT_FUNCTION
?
2374 SIZ_FUNCTION
: SIZ_TEXT
;
2375 GetFont() *= Fraction (rFormat
.GetRelSize(nSizeDesc
), 100);
2377 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
2378 aTmpDev
.SetFont(GetFont());
2380 SmRect::operator = (SmRect(aTmpDev
, &rFormat
, aText
, GetFont().GetBorderWidth()));
2383 void SmTextNode::CreateTextFromNode(String
&rText
)
2386 if (GetToken().eType
== TTEXT
)
2393 SmParser aParseTest
;
2394 SmNode
*pTable
= aParseTest
.Parse(GetToken().aText
);
2396 if ( (pTable
->GetType() == NTABLE
) && (pTable
->GetNumSubNodes() == 1) )
2398 SmNode
*pResult
= pTable
->GetSubNode(0);
2399 if ( (pResult
->GetType() == NLINE
) &&
2400 (pResult
->GetNumSubNodes() == 1) )
2402 pResult
= pResult
->GetSubNode(0);
2403 if ( (pResult
->GetType() == NEXPRESSION
) &&
2404 (pResult
->GetNumSubNodes() == 1) )
2406 pResult
= pResult
->GetSubNode(0);
2407 if (pResult
->GetType() == NTEXT
)
2414 if ((GetToken().eType
== TIDENT
) && (GetFontDesc() == FNT_FUNCTION
))
2416 //Search for existing functions and remove extraenous keyword
2427 rText
.Append(GetToken().aText
);
2435 void SmTextNode::GetAccessibleText( OUStringBuffer
&rText
) const
2437 rText
.append(aText
);
2440 void SmTextNode::AdjustFontDesc()
2442 if (GetToken().eType
== TTEXT
)
2443 nFontDesc
= FNT_TEXT
;
2444 else if(GetToken().eType
== TFUNC
)
2445 nFontDesc
= FNT_FUNCTION
;
2448 const SmTokenTableEntry
*pEntry
= SmParser::GetTokenTableEntry( aText
);
2449 if (pEntry
&& pEntry
->nGroup
== TGFUNCTION
) {
2450 nTok
= pEntry
->eType
;
2451 nFontDesc
= FNT_FUNCTION
;
2453 sal_Unicode firstChar
= aText
[0];
2454 if( ('0' <= firstChar
&& firstChar
<= '9') || firstChar
== '.' || firstChar
== ',') {
2455 nFontDesc
= FNT_NUMBER
;
2457 } else if (aText
.getLength() > 1) {
2458 nFontDesc
= FNT_VARIABLE
;
2461 nFontDesc
= FNT_VARIABLE
;
2465 SmToken tok
= GetToken();
2471 sal_Unicode
SmTextNode::ConvertSymbolToUnicode(sal_Unicode nIn
)
2473 //Find the best match in accepted unicode for our private area symbols
2474 static const sal_Unicode aStarMathPrivateToUnicode
[] =
2476 0x2030, 0xF613, 0xF612, 0x002B, 0x003C, 0x003E, 0xE425, 0xE421, 0xE088, 0x2208,
2477 0x0192, 0x2026, 0x2192, 0x221A, 0x221A, 0x221A, 0xE090, 0x005E, 0x02C7, 0x02D8,
2478 0x00B4, 0x0060, 0x02DC, 0x00AF, 0x0362, 0xE099, 0xE09A, 0x20DB, 0xE09C, 0xE09D,
2479 0x0028, 0x0029, 0x2220, 0x22AF, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7,
2480 0x002F, 0x005C, 0x274F, 0xE0AB, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03A0,
2481 0x03a3, 0x03a5, 0x03a6, 0x03a8, 0x03A9, 0x03B1, 0x03B2, 0x03b3, 0x03b4, 0x03b5,
2482 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
2483 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03b5,
2484 0x03d1, 0x03d6, 0xE0D2, 0x03db, 0x2118, 0x2202, 0x2129, 0xE0D7, 0xE0D8, 0x22A4,
2485 0xE0DA, 0x2190, 0x2191, 0x2193
2487 if ((nIn
>= 0xE080) && (nIn
<= 0xE0DD))
2488 nIn
= aStarMathPrivateToUnicode
[nIn
-0xE080];
2490 //For whatever unicode glyph that equation editor doesn't ship with that
2491 //we have a possible match we can munge it to.
2504 /**************************************************************************/
2506 void SmMatrixNode::CreateTextFromNode(String
&rText
)
2508 rText
+= "matrix {";
2509 for (sal_uInt16 i
= 0; i
< nNumRows
; i
++)
2511 for (sal_uInt16 j
= 0; j
< nNumCols
; j
++)
2513 SmNode
*pNode
= GetSubNode(i
* nNumCols
+ j
);
2515 pNode
->CreateTextFromNode(rText
);
2516 if (j
!= nNumCols
-1)
2519 if (i
!= nNumRows
-1)
2522 rText
= comphelper::string::stripEnd(rText
, ' ');
2527 void SmMatrixNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
2532 // initialize array that is to hold the maximum widhts of all
2533 // elements (subnodes) in that column.
2534 long *pColWidth
= new long[nNumCols
];
2535 for (j
= 0; j
< nNumCols
; j
++)
2538 // arrange subnodes and calculate the aboves arrays contents
2539 sal_uInt16 nNodes
= GetNumSubNodes();
2540 for (i
= 0; i
< nNodes
; i
++)
2542 sal_uInt16 nIdx
= nNodes
- 1 - i
;
2543 if (NULL
!= (pNode
= GetSubNode(nIdx
)))
2545 pNode
->Arrange(rDev
, rFormat
);
2546 int nCol
= nIdx
% nNumCols
;
2547 pColWidth
[nCol
] = std::max(pColWidth
[nCol
], pNode
->GetItalicWidth());
2551 // norm distance from which the following two are calcutated
2552 const int nNormDist
= 3 * GetFont().GetSize().Height();
2554 // define horizontal and vertical minimal distances that separate
2556 long nHorDist
= nNormDist
* rFormat
.GetDistance(DIS_MATRIXCOL
) / 100L,
2557 nVerDist
= nNormDist
* rFormat
.GetDistance(DIS_MATRIXROW
) / 100L;
2559 // build array that holds the leftmost position for each column
2560 long *pColLeft
= new long[nNumCols
];
2562 for (j
= 0; j
< nNumCols
; j
++)
2564 nX
+= pColWidth
[j
] + nHorDist
;
2569 SmRect::operator = (SmRect());
2570 for (i
= 0; i
< nNumRows
; i
++)
2571 { aLineRect
= SmRect();
2572 for (j
= 0; j
< nNumCols
; j
++)
2573 { SmNode
*pTmpNode
= GetSubNode(i
* nNumCols
+ j
);
2574 OSL_ENSURE(pTmpNode
, "Sm: NULL pointer");
2576 const SmRect
&rNodeRect
= pTmpNode
->GetRect();
2578 // align all baselines in that row if possible
2579 aPos
= rNodeRect
.AlignTo(aLineRect
, RP_RIGHT
, RHA_CENTER
, RVA_BASELINE
);
2580 aPos
.X() += nHorDist
;
2582 // get horizontal alignment
2583 const SmNode
*pCoNode
= pTmpNode
->GetLeftMost();
2584 RectHorAlign eHorAlign
= pCoNode
->GetRectHorAlign();
2586 // caculate horizontal position of element depending on column
2587 // and horizontal alignment
2590 aPos
.X() = rNodeRect
.GetLeft() + pColLeft
[j
];
2593 aPos
.X() = rNodeRect
.GetLeft() + pColLeft
[j
]
2595 - rNodeRect
.GetItalicCenterX();
2598 aPos
.X() = rNodeRect
.GetLeft() + pColLeft
[j
]
2599 + pColWidth
[j
] - rNodeRect
.GetItalicWidth();
2603 pTmpNode
->MoveTo(aPos
);
2604 aLineRect
.ExtendBy(rNodeRect
, RCP_XOR
);
2607 aPos
= aLineRect
.AlignTo(*this, RP_BOTTOM
, RHA_CENTER
, RVA_BASELINE
);
2608 aPos
.Y() += nVerDist
;
2610 // move 'aLineRect' and rectangles in that line to final position
2611 aDelta
.X() = 0; // since horizontal alignment is already done
2612 aDelta
.Y() = aPos
.Y() - aLineRect
.GetTop();
2613 aLineRect
.Move(aDelta
);
2614 for (j
= 0; j
< nNumCols
; j
++)
2615 if (NULL
!= (pNode
= GetSubNode(i
* nNumCols
+ j
)))
2616 pNode
->Move(aDelta
);
2618 ExtendBy(aLineRect
, RCP_NONE
);
2622 delete [] pColWidth
;
2626 void SmMatrixNode::SetRowCol(sal_uInt16 nMatrixRows
, sal_uInt16 nMatrixCols
)
2628 nNumRows
= nMatrixRows
;
2629 nNumCols
= nMatrixCols
;
2633 SmNode
* SmMatrixNode::GetLeftMost()
2639 /**************************************************************************/
2642 SmMathSymbolNode::SmMathSymbolNode(const SmToken
&rNodeToken
)
2643 : SmSpecialNode(NMATH
, rNodeToken
, FNT_MATH
)
2645 sal_Unicode cChar
= GetToken().cMathChar
;
2646 if ((sal_Unicode
) '\0' != cChar
)
2647 SetText(OUString(cChar
));
2650 void SmMathSymbolNode::AdaptToX(const OutputDevice
&rDev
, sal_uLong nWidth
)
2652 // Since there is no function to do this, we try to approximate it:
2653 Size
aFntSize (GetFont().GetSize());
2655 //! however the result is a bit better with 'nWidth' as initial font width
2656 aFntSize
.Width() = nWidth
;
2657 GetFont().SetSize(aFntSize
);
2659 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
2660 aTmpDev
.SetFont(GetFont());
2662 // get denominator of error factor for width
2663 long nTmpBorderWidth
= GetFont().GetBorderWidth();
2664 long nDenom
= SmRect(aTmpDev
, NULL
, GetText(), nTmpBorderWidth
).GetItalicWidth();
2666 // scale fontwidth with this error factor
2667 aFntSize
.Width() *= nWidth
;
2668 aFntSize
.Width() /= nDenom
? nDenom
: 1;
2670 GetFont().SetSize(aFntSize
);
2673 void SmMathSymbolNode::AdaptToY(const OutputDevice
&rDev
, sal_uLong nHeight
)
2675 GetFont().FreezeBorderWidth();
2676 Size
aFntSize (GetFont().GetSize());
2678 // Since we only want to scale the height, we might have
2679 // to determine the font width in order to keep it
2680 if (aFntSize
.Width() == 0)
2682 OutputDevice
&rDevNC
= (OutputDevice
&) rDev
;
2683 rDevNC
.Push(PUSH_FONT
| PUSH_MAPMODE
);
2684 rDevNC
.SetFont(GetFont());
2685 aFntSize
.Width() = rDev
.GetFontMetric().GetSize().Width();
2688 OSL_ENSURE(aFntSize
.Width() != 0, "Sm: ");
2690 //! however the result is a bit better with 'nHeight' as initial
2692 aFntSize
.Height() = nHeight
;
2693 GetFont().SetSize(aFntSize
);
2695 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
2696 aTmpDev
.SetFont(GetFont());
2698 // get denominator of error factor for height
2699 long nTmpBorderWidth
= GetFont().GetBorderWidth();
2700 long nDenom
= SmRect(aTmpDev
, NULL
, GetText(), nTmpBorderWidth
).GetHeight();
2702 // scale fontwidth with this error factor
2703 aFntSize
.Height() *= nHeight
;
2704 aFntSize
.Height() /= nDenom
? nDenom
: 1;
2706 GetFont().SetSize(aFntSize
);
2710 void SmMathSymbolNode::Prepare(const SmFormat
&rFormat
, const SmDocShell
&rDocShell
)
2712 SmNode::Prepare(rFormat
, rDocShell
);
2714 GetFont() = rFormat
.GetFont(GetFontDesc());
2715 // use same font size as is used for variables
2716 GetFont().SetSize( rFormat
.GetFont( FNT_VARIABLE
).GetSize() );
2718 OSL_ENSURE(GetFont().GetCharSet() == RTL_TEXTENCODING_SYMBOL
||
2719 GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE
,
2720 "wrong charset for character from StarMath/OpenSymbol font");
2722 Flags() |= FLG_FONT
| FLG_ITALIC
;
2726 void SmMathSymbolNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
2728 const OUString
&rText
= GetText();
2730 if (rText
.isEmpty() || rText
[0] == '\0')
2731 { SmRect::operator = (SmRect());
2735 PrepareAttributes();
2737 GetFont() *= Fraction (rFormat
.GetRelSize(SIZ_TEXT
), 100);
2739 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
2740 aTmpDev
.SetFont(GetFont());
2742 SmRect::operator = (SmRect(aTmpDev
, &rFormat
, rText
, GetFont().GetBorderWidth()));
2745 void SmMathSymbolNode::CreateTextFromNode(String
&rText
)
2748 MathType::LookupChar(GetToken().cMathChar
, sStr
);
2752 void SmRectangleNode::CreateTextFromNode(String
&rText
)
2754 switch (GetToken().eType
)
2757 rText
+= "underline ";
2760 rText
+= "overline ";
2763 rText
+= "overstrike ";
2770 void SmAttributNode::CreateTextFromNode(String
&rText
)
2773 sal_uInt16 nSize
= GetNumSubNodes();
2774 OSL_ENSURE(nSize
== 2, "Node missing members");
2776 sal_Unicode nLast
=0;
2777 if (NULL
!= (pNode
= GetSubNode(0)))
2780 pNode
->CreateTextFromNode(aStr
);
2785 nLast
= aStr
.GetChar(0);
2788 case 0xAF: // MACRON
2789 rText
+= "overline ";
2791 case MS_DOT
: // DOT ABOVE
2794 case 0x2dc: // SMALL TILDE
2795 rText
+= "widetilde ";
2797 case MS_DDOT
: // DIAERESIS
2803 case MS_DDDOT
: // COMBINING THREE DOTS ABOVE
2806 case MS_ACUTE
: // COMBINING ACUTE ACCENT
2809 case MS_GRAVE
: // COMBINING GRAVE ACCENT
2812 case MS_CHECK
: // COMBINING CARON
2815 case MS_BREVE
: // COMBINING BREVE
2818 case MS_CIRCLE
: // COMBINING RING ABOVE
2821 case MS_VEC
: // COMBINING RIGHT ARROW ABOVE
2824 case MS_TILDE
: // COMBINING TILDE
2827 case MS_HAT
: // COMBINING CIRCUMFLEX ACCENT
2830 case MS_BAR
: // COMBINING MACRON
2834 rText
.Append(nLast
);
2841 if (NULL
!= (pNode
= GetSubNode(1)))
2842 pNode
->CreateTextFromNode(rText
);
2844 rText
= comphelper::string::stripEnd(rText
, ' ');
2846 if (nLast
== 0xE082)
2847 rText
+= " overbrace {}";
2852 /**************************************************************************/
2854 static bool lcl_IsFromGreekSymbolSet( const String
&rTokenText
)
2858 // valid symbol name needs to have a '%' at pos 0 and at least an additonal char
2859 if (rTokenText
.Len() > 2 && rTokenText
.GetBuffer()[0] == (sal_Unicode
)'%')
2861 String
aName( rTokenText
.Copy(1) );
2862 SmSym
*pSymbol
= SM_MOD()->GetSymbolManager().GetSymbolByName( aName
);
2863 if (pSymbol
&& GetExportSymbolSetName(pSymbol
->GetSymbolSetName()) == "Greek")
2871 SmSpecialNode::SmSpecialNode(SmNodeType eNodeType
, const SmToken
&rNodeToken
, sal_uInt16 _nFontDesc
) :
2872 SmTextNode(eNodeType
, rNodeToken
, _nFontDesc
)
2874 bIsFromGreekSymbolSet
= lcl_IsFromGreekSymbolSet( rNodeToken
.aText
);
2878 SmSpecialNode::SmSpecialNode(const SmToken
&rNodeToken
) :
2879 SmTextNode(NSPECIAL
, rNodeToken
, FNT_MATH
) // default Font isn't always correct!
2881 bIsFromGreekSymbolSet
= lcl_IsFromGreekSymbolSet( rNodeToken
.aText
);
2885 void SmSpecialNode::Prepare(const SmFormat
&rFormat
, const SmDocShell
&rDocShell
)
2887 SmNode::Prepare(rFormat
, rDocShell
);
2890 SmModule
*pp
= SM_MOD();
2892 OUString
aName(GetToken().aText
.copy(1));
2893 if (NULL
!= (pSym
= pp
->GetSymbolManager().GetSymbolByName( aName
)))
2895 sal_UCS4 cChar
= pSym
->GetCharacter();
2896 OUString
aTmp( &cChar
, 1 );
2898 GetFont() = pSym
->GetFace();
2902 SetText( GetToken().aText
);
2903 GetFont() = rFormat
.GetFont(FNT_VARIABLE
);
2905 // use same font size as is used for variables
2906 GetFont().SetSize( rFormat
.GetFont( FNT_VARIABLE
).GetSize() );
2908 // Actually only WEIGHT_NORMAL and WEIGHT_BOLD should occur... However, the sms-file also
2909 // contains e.g. 'WEIGHT_ULTRALIGHT'. Consequently, compare here with '>' instead of '!='.
2910 // (In the long term the necessity for 'PrepareAttribut' and thus also for this here should be dropped)
2912 //! see also SmFontStyles::GetStyleName
2913 if (IsItalic( GetFont() ))
2914 SetAttribut(ATTR_ITALIC
);
2915 if (IsBold( GetFont() ))
2916 SetAttribut(ATTR_BOLD
);
2918 Flags() |= FLG_FONT
;
2920 if (bIsFromGreekSymbolSet
)
2922 OSL_ENSURE( GetText().getLength() == 1, "a symbol should only consist of 1 char!" );
2923 bool bItalic
= false;
2924 sal_Int16 nStyle
= rFormat
.GetGreekCharStyle();
2925 OSL_ENSURE( nStyle
>= 0 && nStyle
<= 2, "unexpected value for GreekCharStyle" );
2928 else if (nStyle
== 2)
2930 const OUString
& rTmp(GetText());
2933 const sal_Unicode cUppercaseAlpha
= 0x0391;
2934 const sal_Unicode cUppercaseOmega
= 0x03A9;
2935 sal_Unicode cChar
= rTmp
[0];
2936 // uppercase letters should be straight and lowercase letters italic
2937 bItalic
= !(cUppercaseAlpha
<= cChar
&& cChar
<= cUppercaseOmega
);
2942 Attributes() |= ATTR_ITALIC
;
2944 Attributes() &= ~ATTR_ITALIC
;;
2949 void SmSpecialNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
2951 PrepareAttributes();
2953 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
2954 aTmpDev
.SetFont(GetFont());
2956 SmRect::operator = (SmRect(aTmpDev
, &rFormat
, GetText(), GetFont().GetBorderWidth()));
2959 /**************************************************************************/
2962 void SmGlyphSpecialNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
2964 PrepareAttributes();
2966 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
2967 aTmpDev
.SetFont(GetFont());
2969 SmRect::operator = (SmRect(aTmpDev
, &rFormat
, GetText(),
2970 GetFont().GetBorderWidth()).AsGlyphRect());
2974 /**************************************************************************/
2977 void SmPlaceNode::Prepare(const SmFormat
&rFormat
, const SmDocShell
&rDocShell
)
2979 SmNode::Prepare(rFormat
, rDocShell
);
2981 GetFont().SetColor(COL_GRAY
);
2982 Flags() |= FLG_COLOR
| FLG_FONT
| FLG_ITALIC
;
2986 void SmPlaceNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
2988 PrepareAttributes();
2990 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
2991 aTmpDev
.SetFont(GetFont());
2993 SmRect::operator = (SmRect(aTmpDev
, &rFormat
, GetText(), GetFont().GetBorderWidth()));
2997 /**************************************************************************/
3000 void SmErrorNode::Prepare(const SmFormat
&rFormat
, const SmDocShell
&rDocShell
)
3002 SmNode::Prepare(rFormat
, rDocShell
);
3004 GetFont().SetColor(COL_RED
);
3005 Flags() |= FLG_VISIBLE
| FLG_BOLD
| FLG_ITALIC
3006 | FLG_COLOR
| FLG_FONT
| FLG_SIZE
;
3010 void SmErrorNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
3012 PrepareAttributes();
3014 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
3015 aTmpDev
.SetFont(GetFont());
3017 const OUString
&rText
= GetText();
3018 SmRect::operator = (SmRect(aTmpDev
, &rFormat
, rText
, GetFont().GetBorderWidth()));
3022 /**************************************************************************/
3025 void SmBlankNode::IncreaseBy(const SmToken
&rToken
)
3027 switch(rToken
.eType
)
3029 case TBLANK
: nNum
+= 4; break;
3030 case TSBLANK
: nNum
+= 1; break;
3037 void SmBlankNode::Prepare(const SmFormat
&rFormat
, const SmDocShell
&rDocShell
)
3039 SmNode::Prepare(rFormat
, rDocShell
);
3041 // Here it need/should not be the StarMath font, so that for the character
3042 // used in Arrange a normal (non-clipped) rectangle is generated
3043 GetFont() = rFormat
.GetFont(FNT_VARIABLE
);
3045 Flags() |= FLG_FONT
| FLG_BOLD
| FLG_ITALIC
;
3049 void SmBlankNode::Arrange(const OutputDevice
&rDev
, const SmFormat
&rFormat
)
3051 SmTmpDevice
aTmpDev ((OutputDevice
&) rDev
, true);
3052 aTmpDev
.SetFont(GetFont());
3054 // make distance depend on the font height
3055 // (so that it increases when scaling (e.g. size *2 {a ~ b})
3056 long nDist
= GetFont().GetSize().Height() / 10L,
3057 nSpace
= nNum
* nDist
;
3059 // get a SmRect with Baseline and all the bells and whistles
3060 SmRect::operator = (SmRect(aTmpDev
, &rFormat
, OUString(' '),
3061 GetFont().GetBorderWidth()));
3063 // and resize it to the requested size
3064 SetItalicSpaces(0, 0);
3068 /**************************************************************************/
3069 //Implementation of all accept methods for SmVisitor
3071 void SmNode::Accept(SmVisitor
*){
3072 //This method is only implemented to avoid making SmNode abstract because an
3073 //obscure copy constructor is used... I can't find it's implementation, and
3074 //don't want to figure out how to fix it... If you want to, just delete this
3075 //method, making SmNode abstract, and see where you can an problem with that.
3076 OSL_FAIL("SmNode should not be visitable!");
3079 void SmTableNode::Accept(SmVisitor
* pVisitor
) {
3080 pVisitor
->Visit(this);
3083 void SmBraceNode::Accept(SmVisitor
* pVisitor
) {
3084 pVisitor
->Visit(this);
3087 void SmBracebodyNode::Accept(SmVisitor
* pVisitor
) {
3088 pVisitor
->Visit(this);
3091 void SmOperNode::Accept(SmVisitor
* pVisitor
) {
3092 pVisitor
->Visit(this);
3095 void SmAlignNode::Accept(SmVisitor
* pVisitor
) {
3096 pVisitor
->Visit(this);
3099 void SmAttributNode::Accept(SmVisitor
* pVisitor
) {
3100 pVisitor
->Visit(this);
3103 void SmFontNode::Accept(SmVisitor
* pVisitor
) {
3104 pVisitor
->Visit(this);
3107 void SmUnHorNode::Accept(SmVisitor
* pVisitor
) {
3108 pVisitor
->Visit(this);
3111 void SmBinHorNode::Accept(SmVisitor
* pVisitor
) {
3112 pVisitor
->Visit(this);
3115 void SmBinVerNode::Accept(SmVisitor
* pVisitor
) {
3116 pVisitor
->Visit(this);
3119 void SmBinDiagonalNode::Accept(SmVisitor
* pVisitor
) {
3120 pVisitor
->Visit(this);
3123 void SmSubSupNode::Accept(SmVisitor
* pVisitor
) {
3124 pVisitor
->Visit(this);
3127 void SmMatrixNode::Accept(SmVisitor
* pVisitor
) {
3128 pVisitor
->Visit(this);
3131 void SmPlaceNode::Accept(SmVisitor
* pVisitor
) {
3132 pVisitor
->Visit(this);
3135 void SmTextNode::Accept(SmVisitor
* pVisitor
) {
3136 pVisitor
->Visit(this);
3139 void SmSpecialNode::Accept(SmVisitor
* pVisitor
) {
3140 pVisitor
->Visit(this);
3143 void SmGlyphSpecialNode::Accept(SmVisitor
* pVisitor
) {
3144 pVisitor
->Visit(this);
3147 void SmMathSymbolNode::Accept(SmVisitor
* pVisitor
) {
3148 pVisitor
->Visit(this);
3151 void SmBlankNode::Accept(SmVisitor
* pVisitor
) {
3152 pVisitor
->Visit(this);
3155 void SmErrorNode::Accept(SmVisitor
* pVisitor
) {
3156 pVisitor
->Visit(this);
3159 void SmLineNode::Accept(SmVisitor
* pVisitor
) {
3160 pVisitor
->Visit(this);
3163 void SmExpressionNode::Accept(SmVisitor
* pVisitor
) {
3164 pVisitor
->Visit(this);
3167 void SmPolyLineNode::Accept(SmVisitor
* pVisitor
) {
3168 pVisitor
->Visit(this);
3171 void SmRootNode::Accept(SmVisitor
* pVisitor
) {
3172 pVisitor
->Visit(this);
3175 void SmRootSymbolNode::Accept(SmVisitor
* pVisitor
) {
3176 pVisitor
->Visit(this);
3179 void SmRectangleNode::Accept(SmVisitor
* pVisitor
) {
3180 pVisitor
->Visit(this);
3183 void SmVerticalBraceNode::Accept(SmVisitor
* pVisitor
) {
3184 pVisitor
->Visit(this);
3187 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */