summaryrefslogtreecommitdiff
path: root/binfilter/bf_starmath/source/starmath_node.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'binfilter/bf_starmath/source/starmath_node.cxx')
-rw-r--r--binfilter/bf_starmath/source/starmath_node.cxx2468
1 files changed, 2468 insertions, 0 deletions
diff --git a/binfilter/bf_starmath/source/starmath_node.cxx b/binfilter/bf_starmath/source/starmath_node.cxx
new file mode 100644
index 000000000000..fcd29193b9f9
--- /dev/null
+++ b/binfilter/bf_starmath/source/starmath_node.cxx
@@ -0,0 +1,2468 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifdef _MSC_VER
+#pragma hdrstop
+#endif
+#define APPEND(str,ascii) str.AppendAscii(RTL_CONSTASCII_STRINGPARAM(ascii))
+
+#include <vcl/lineinfo.hxx>
+
+
+#include "symbol.hxx"
+#include <document.hxx>
+#include "mathtype.hxx"
+
+#include <math.h>
+#include <float.h>
+namespace binfilter {
+
+// define this to draw rectangles for debugging
+//#define SM_RECT_DEBUG
+
+////////////////////////////////////////
+// SmTmpDevice
+// Allows for font and color changes. The original settings will be restored
+// in the destructor.
+// It's main purpose is to allow for the "const" in the 'OutputDevice'
+// argument in the 'Arrange' functions and restore changes made in the 'Draw'
+// functions.
+// Usually a MapMode of 1/100th mm will be used.
+//
+
+/*N*/ class SmTmpDevice
+/*N*/ {
+/*N*/ OutputDevice &rOutDev;
+/*N*/
+/*N*/ // disallow use of copy-constructor and assignment-operator
+/*N*/ SmTmpDevice(const SmTmpDevice &rTmpDev);
+/*N*/ SmTmpDevice & operator = (const SmTmpDevice &rTmpDev);
+/*N*/
+/*N*/ Color Impl_GetColor( const Color& rColor );
+/*N*/
+/*N*/ public:
+/*N*/ SmTmpDevice(OutputDevice &rTheDev, BOOL bUseMap100th_mm);
+/*N*/ ~SmTmpDevice() { rOutDev.Pop(); }
+/*N*/
+/*N*/ void SetFont(const Font &rNewFont);
+/*N*/
+/*N*/ void SetLineColor( const Color& rColor ) { rOutDev.SetLineColor( Impl_GetColor(rColor) ); }
+/*N*/ void SetFillColor( const Color& rColor ) { rOutDev.SetFillColor( Impl_GetColor(rColor) ); }
+/*N*/ void SetTextColor( const Color& rColor ) { rOutDev.SetTextColor( Impl_GetColor(rColor) ); }
+/*N*/
+/*N*/ operator OutputDevice & () { return rOutDev; }
+/*N*/ };
+
+
+/*N*/ SmTmpDevice::SmTmpDevice(OutputDevice &rTheDev, BOOL bUseMap100th_mm) :
+/*N*/ rOutDev(rTheDev)
+/*N*/ {
+/*N*/ rOutDev.Push( PUSH_FONT | PUSH_MAPMODE |
+/*N*/ PUSH_LINECOLOR | PUSH_FILLCOLOR | PUSH_TEXTCOLOR );
+/*N*/ if (bUseMap100th_mm && MAP_100TH_MM != rOutDev.GetMapMode().GetMapUnit())
+/*N*/ {
+/*?*/ DBG_ERROR( "incorrect MapMode?" );
+/*?*/ rOutDev.SetMapMode( MAP_100TH_MM ); //Immer fuer 100% fomatieren
+/*N*/ }
+/*N*/ }
+
+
+/*N*/ Color SmTmpDevice::Impl_GetColor( const Color& rColor )
+/*N*/ {
+/*N*/ ColorData nNewCol = rColor.GetColor();
+/*N*/ if (COL_AUTO == nNewCol)
+/*N*/ {
+/*N*/ if (OUTDEV_PRINTER == rOutDev.GetOutDevType())
+/*N*/ nNewCol = COL_BLACK;
+/*N*/ else
+/*N*/ {
+/*N*/ Color aBgCol( rOutDev.GetBackground().GetColor() );
+/*N*/ if (OUTDEV_WINDOW == rOutDev.GetOutDevType())
+/*N*/ aBgCol = ((Window &) rOutDev).GetDisplayBackground().GetColor();
+/*N*/
+/*N*/ nNewCol = SM_MOD1()->GetColorConfig().GetColorValue(FONTCOLOR).nColor;
+/*N*/
+/*N*/ Color aTmpColor( nNewCol );
+/*N*/ if (aBgCol.IsDark() && aTmpColor.IsDark())
+/*N*/ nNewCol = COL_WHITE;
+/*N*/ else if (aBgCol.IsBright() && aTmpColor.IsBright())
+/*N*/ nNewCol = COL_BLACK;
+/*N*/ }
+/*N*/ }
+/*N*/ return Color( nNewCol );
+/*N*/ }
+
+
+/*N*/ void SmTmpDevice::SetFont(const Font &rNewFont)
+/*N*/ {
+/*N*/ rOutDev.SetFont( rNewFont );
+/*N*/ rOutDev.SetTextColor( Impl_GetColor( rNewFont.GetColor() ) );
+/*N*/ }
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+/*N*/ SmNode::SmNode(SmNodeType eNodeType, const SmToken &rNodeToken)
+/*N*/ {
+/*N*/ eType = eNodeType;
+/*N*/ eScaleMode = SCALE_NONE;
+/*N*/ aNodeToken = rNodeToken;
+/*N*/ nAccIndex = -1;
+/*N*/ }
+
+
+/*N*/ SmNode::~SmNode()
+/*N*/ {
+/*N*/ }
+
+
+/*N*/ BOOL SmNode::IsVisible() const
+/*N*/ {
+/*N*/ return FALSE;
+/*N*/ }
+
+
+/*N*/ USHORT SmNode::GetNumSubNodes() const
+/*N*/ {
+/*N*/ return 0;
+/*N*/ }
+
+
+/*N*/ SmNode * SmNode::GetSubNode(USHORT nIndex)
+/*N*/ {
+/*N*/ return NULL;
+/*N*/ }
+
+
+/*N*/ SmNode * SmNode::GetLeftMost()
+/*N*/ // returns leftmost node of current subtree.
+/*N*/ //! (this assumes the one with index 0 is always the leftmost subnode
+/*N*/ //! for the current node).
+/*N*/ {
+/*N*/ SmNode *pNode = GetNumSubNodes() > 0 ?
+/*N*/ GetSubNode(0) : NULL;
+/*N*/
+/*N*/ return pNode ? pNode->GetLeftMost() : this;
+/*N*/ }
+
+
+void SmNode::SetPhantom(BOOL bIsPhantomP)
+{
+ if (! (Flags() & FLG_VISIBLE))
+ bIsPhantom = bIsPhantomP;
+
+ SmNode *pNode;
+ USHORT nSize = GetNumSubNodes();
+ for (USHORT i = 0; i < nSize; i++)
+ if (pNode = GetSubNode(i))
+ pNode->SetPhantom(bIsPhantom);
+}
+
+
+void SmNode::SetColor(const Color& rColor)
+{
+ if (! (Flags() & FLG_COLOR))
+ GetFont().SetColor(rColor);
+
+ SmNode *pNode;
+ USHORT nSize = GetNumSubNodes();
+ for (USHORT i = 0; i < nSize; i++)
+ if (pNode = GetSubNode(i))
+ pNode->SetColor(rColor);
+}
+
+
+/*N*/ void SmNode::SetAttribut(USHORT nAttrib)
+/*N*/ {
+/*N*/ if ( nAttrib == ATTR_BOLD && !(Flags() & FLG_BOLD)
+/*N*/ || nAttrib == ATTR_ITALIC && !(Flags() & FLG_ITALIC))
+/*N*/ nAttributes |= nAttrib;
+/*N*/
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ pNode->SetAttribut(nAttrib);
+/*N*/ }
+
+
+/*N*/ void SmNode::ClearAttribut(USHORT nAttrib)
+/*N*/ {
+/*N*/ if ( nAttrib == ATTR_BOLD && !(Flags() & FLG_BOLD)
+/*N*/ || nAttrib == ATTR_ITALIC && !(Flags() & FLG_ITALIC))
+/*N*/ nAttributes &= ~nAttrib;
+/*N*/
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ pNode->ClearAttribut(nAttrib);
+/*N*/ }
+
+
+/*N*/ void SmNode::SetFont(const SmFace &rFace)
+/*N*/ {
+/*N*/ if (!(Flags() & FLG_FONT))
+/*N*/ GetFont() = rFace;
+/*N*/
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ pNode->SetFont(rFace);
+/*N*/ }
+
+
+/*N*/ void SmNode::SetFontSize(const Fraction &rSize, USHORT nType)
+/*N*/ //! 'rSize' is in units of pts
+/*N*/ {
+/*N*/ Size aSize;
+/*N*/
+/*N*/ if (!(Flags() & FLG_SIZE))
+/*N*/ {
+/*N*/ Fraction aVal (SmPtsTo100th_mm(rSize.GetNumerator()),
+/*N*/ rSize.GetDenominator());
+/*N*/ //long nHeight = ::rtl::math::round(aVal);
+/*N*/ long nHeight = (long)aVal;
+/*N*/
+/*N*/ aSize = GetFont().GetSize();
+/*N*/ aSize.Width() = 0;
+/*N*/ switch(nType)
+/*N*/ {
+/*N*/ case FNTSIZ_ABSOLUT:
+/*N*/ aSize.Height() = nHeight;
+/*N*/ break;
+/*N*/
+/*N*/ case FNTSIZ_PLUS:
+/*?*/ aSize.Height() += nHeight;
+/*?*/ break;
+/*N*/
+/*N*/ case FNTSIZ_MINUS:
+/*?*/ aSize.Height() -= nHeight;
+/*?*/ break;
+/*N*/
+/*N*/ case FNTSIZ_MULTIPLY:
+/*N*/ aSize.Height() = (long) (Fraction(aSize.Height()) * rSize);
+/*N*/ break;
+/*N*/
+/*N*/ case FNTSIZ_DIVIDE:
+/*?*/ if (rSize != Fraction(0L))
+/*?*/ aSize.Height() = (long) (Fraction(aSize.Height()) / rSize);
+/*N*/ break;
+/*N*/ }
+/*N*/
+/*N*/ // check the requested size against maximum value
+/*N*/ static int __READONLY_DATA nMaxVal = SmPtsTo100th_mm(128);
+/*N*/ if (aSize.Height() > nMaxVal)
+/*?*/ aSize.Height() = nMaxVal;
+/*N*/
+/*N*/ GetFont().SetSize(aSize);
+/*N*/ }
+/*N*/
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ pNode->SetFontSize(rSize, nType);
+/*N*/ }
+
+
+/*N*/ void SmNode::SetSize(const Fraction &rSize)
+/*N*/ {
+/*N*/ GetFont() *= rSize;
+/*N*/
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ pNode->SetSize(rSize);
+/*N*/ }
+
+
+/*N*/ void SmNode::SetRectHorAlign(RectHorAlign eHorAlign, BOOL bApplyToSubTree )
+/*N*/ {
+/*N*/ if (!(Flags() & FLG_HORALIGN))
+/*N*/ eRectHorAlign = eHorAlign;
+/*N*/
+/*N*/ if (bApplyToSubTree)
+/*N*/ {
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*?*/ if (pNode = GetSubNode(i))
+/*?*/ pNode->SetRectHorAlign(eHorAlign);
+/*N*/ }
+/*N*/ }
+
+
+/*N*/ void SmNode::PrepareAttributes()
+/*N*/ {
+/*N*/ GetFont().SetWeight((Attributes() & ATTR_BOLD) ? WEIGHT_BOLD : WEIGHT_NORMAL);
+/*N*/ GetFont().SetItalic((Attributes() & ATTR_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE);
+/*N*/ }
+
+
+/*N*/ void SmNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
+/*N*/ {
+/*N*/ #if OSL_DEBUG_LEVEL > 1
+/*N*/ bIsDebug = TRUE;
+/*N*/ #else
+/*N*/ bIsDebug = FALSE;
+/*N*/ #endif
+/*N*/ bIsPhantom = FALSE;
+/*N*/ nFlags = 0;
+/*N*/ nAttributes = 0;
+/*N*/
+/*N*/ switch (rFormat.GetHorAlign())
+/*N*/ { case AlignLeft: eRectHorAlign = RHA_LEFT; break;
+/*N*/ case AlignCenter: eRectHorAlign = RHA_CENTER; break;
+/*?*/ case AlignRight: eRectHorAlign = RHA_RIGHT; break;
+/*N*/ }
+/*N*/
+/*N*/ GetFont() = rFormat.GetFont(FNT_MATH);
+/*N*/ //GetFont().SetCharSet(RTL_TEXTENCODING_SYMBOL);
+/*N*/ DBG_ASSERT( GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE,
+/*N*/ "unexpected CharSet" );
+/*N*/ GetFont().SetWeight(WEIGHT_NORMAL);
+/*N*/ GetFont().SetItalic(ITALIC_NONE);
+/*N*/
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ pNode->Prepare(rFormat, rDocShell);
+/*N*/ }
+
+
+
+
+#ifdef MAC
+#pragma segment FrmNode_02
+
+#else
+
+#endif
+
+
+/*N*/ void SmNode::Move(const Point& rPosition)
+/*N*/ {
+/*N*/ if (rPosition.X() == 0 && rPosition.Y() == 0)
+/*N*/ return;
+/*N*/
+/*N*/ SmRect::Move(rPosition);
+/*N*/
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ pNode->Move(rPosition);
+/*N*/ }
+
+
+/*N*/ void SmNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ pNode->Arrange(rDev, rFormat);
+/*N*/ }
+
+/*N*/ void SmNode::CreateTextFromNode(String &rText)
+/*N*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001
+/*N*/ }
+
+
+/*N*/ void SmNode::AdaptToX(const OutputDevice &rDev, ULONG nWidth)
+/*N*/ {
+/*N*/ }
+
+
+/*N*/ void SmNode::AdaptToY(const OutputDevice &rDev, ULONG nHeight)
+/*N*/ {
+/*N*/ }
+
+
+/*N*/ void SmNode::Draw(OutputDevice &rDev, const Point &rPosition) const
+/*N*/ {
+/*N*/ if (IsPhantom())
+/*N*/ return;
+/*N*/
+/*N*/ const SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ { Point aOffset (pNode->GetTopLeft() - GetTopLeft());
+/*N*/ pNode->Draw(rDev, rPosition + aOffset);
+/*N*/ }
+/*N*/
+/*N*/ #ifdef SM_RECT_DEBUG
+/*N*/ if (!IsDebug())
+/*N*/ return;
+/*N*/
+/*N*/ int nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
+/*N*/ SmRect::Draw(rDev, rPosition, nRFlags);
+/*N*/ #endif
+/*N*/ }
+
+/*N*/ const SmNode * SmNode::FindTokenAt(USHORT nRow, USHORT nCol) const
+/*N*/ // returns (first) ** visible ** (sub)node with the tokens text at
+/*N*/ // position 'nRow', 'nCol'.
+/*N*/ //! (there should be exactly one such node if any)
+/*N*/ {
+/*N*/ if ( IsVisible()
+/*N*/ && nRow == GetToken().nRow
+/*N*/ && nCol >= GetToken().nCol && nCol < GetToken().nCol + GetToken().aText.Len())
+/*N*/ return this;
+/*N*/ else
+/*N*/ {
+/*N*/ USHORT nNumSubNodes = GetNumSubNodes();
+/*N*/ for (USHORT i = 0; i < nNumSubNodes; i++)
+/*N*/ { const SmNode *pNode = GetSubNode(i);
+/*N*/
+/*N*/ if (!pNode)
+/*N*/ continue;
+/*N*/
+/*N*/ const SmNode *pResult = pNode->FindTokenAt(nRow, nCol);
+/*N*/ if (pResult)
+/*N*/ return pResult;
+/*N*/ }
+/*N*/ }
+/*N*/
+/*N*/ return 0;
+/*N*/ }
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+
+SmStructureNode::SmStructureNode( const SmStructureNode &rNode ) :
+ SmNode( rNode.GetType(), rNode.GetToken() )
+{
+ ULONG i;
+ for (i = 0; i < aSubNodes.GetSize(); i++)
+ delete aSubNodes.Get(i);
+ aSubNodes.Clear();
+
+ ULONG nSize = rNode.aSubNodes.GetSize();
+ aSubNodes.SetSize( nSize );
+ for (i = 0; i < nSize; ++i)
+ {
+ SmNode *pNode = rNode.aSubNodes.Get(i);
+ aSubNodes.Put( i, pNode ? new SmNode( *pNode ) : 0 );
+ }
+}
+
+
+/*N*/ SmStructureNode::~SmStructureNode()
+/*N*/ {
+/*N*/ SmNode *pNode;
+/*N*/
+/*N*/ for (USHORT i = 0; i < GetNumSubNodes(); i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ delete pNode;
+/*N*/ }
+
+
+SmStructureNode & SmStructureNode::operator = ( const SmStructureNode &rNode )
+{
+ SmNode::operator = ( rNode );
+
+ ULONG i;
+ for (i = 0; i < aSubNodes.GetSize(); i++)
+ delete aSubNodes.Get(i);
+ aSubNodes.Clear();
+
+ ULONG nSize = rNode.aSubNodes.GetSize();
+ aSubNodes.SetSize( nSize );
+ for (i = 0; i < nSize; ++i)
+ {
+ SmNode *pNode = rNode.aSubNodes.Get(i);
+ aSubNodes.Put( i, pNode ? new SmNode( *pNode ) : 0 );
+ }
+
+ return *this;
+}
+
+
+/*N*/ void SmStructureNode::SetSubNodes(SmNode *pFirst, SmNode *pSecond, SmNode *pThird)
+/*N*/ {
+/*N*/ if (pFirst)
+/*N*/ aSubNodes.Put(0, pFirst);
+/*N*/ if (pSecond)
+/*N*/ aSubNodes.Put(1, pSecond);
+/*N*/ if (pThird)
+/*N*/ aSubNodes.Put(2, pThird);
+/*N*/ }
+
+
+/*N*/ void SmStructureNode::SetSubNodes(const SmNodeArray &rNodeArray)
+/*N*/ {
+/*N*/ aSubNodes = rNodeArray;
+/*N*/ }
+
+
+/*N*/ BOOL SmStructureNode::IsVisible() const
+/*N*/ {
+/*N*/ return FALSE;
+/*N*/ }
+
+
+/*N*/ USHORT SmStructureNode::GetNumSubNodes() const
+/*N*/ {
+/*N*/ return (USHORT) aSubNodes.GetSize();
+/*N*/ }
+
+
+/*N*/ SmNode * SmStructureNode::GetSubNode(USHORT nIndex)
+/*N*/ {
+/*N*/ return aSubNodes.Get(nIndex);
+/*N*/ }
+
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+/*N*/ BOOL SmVisibleNode::IsVisible() const
+/*N*/ {
+/*N*/ return TRUE;
+/*N*/ }
+
+
+/*N*/ USHORT SmVisibleNode::GetNumSubNodes() const
+/*N*/ {
+/*N*/ return 0;
+/*N*/ }
+
+
+SmNode * SmVisibleNode::GetSubNode(USHORT nIndex)
+{
+ return NULL;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+
+/*N*/ void SmTableNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ // arranges all subnodes in one column
+/*N*/ {
+/*N*/ Point rPosition;
+/*N*/
+/*N*/ USHORT nWidth = 0;
+/*N*/ USHORT nHeight = 0;
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/
+/*N*/ // make distance depend on font size
+/*N*/ long nDist = +(rFormat.GetDistance(DIS_VERTICAL)
+/*N*/ * GetFont().GetSize().Height()) / 100L;
+/*N*/
+/*N*/ if (nSize < 1)
+/*N*/ return;
+/*N*/
+/*N*/ // arrange subnodes and get maximum width of them
+/*N*/ long nMaxWidth = 0,
+/*N*/ nTmp;
+/*N*/ USHORT i;
+/*N*/ for (i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ { pNode->Arrange(rDev, rFormat);
+/*N*/ if ((nTmp = pNode->GetItalicWidth()) > nMaxWidth)
+/*N*/ nMaxWidth = nTmp;
+/*N*/ }
+/*N*/
+/*N*/ Point aPos;
+/*N*/ SmRect::operator = (SmRect(nMaxWidth, 0));
+/*N*/ for (i = 0; i < nSize; i++)
+/*N*/ { if (pNode = GetSubNode(i))
+/*N*/ { const SmRect &rNodeRect = pNode->GetRect();
+/*N*/ const SmNode *pCoNode = pNode->GetLeftMost();
+/*N*/ SmTokenType eType = pCoNode->GetToken().eType;
+/*N*/ RectHorAlign eHorAlign = pCoNode->GetRectHorAlign();
+/*N*/
+/*N*/ aPos = rNodeRect.AlignTo(*this, RP_BOTTOM,
+/*N*/ eHorAlign, RVA_BASELINE);
+/*N*/ if (i)
+/*N*/ aPos.Y() += nDist;
+/*N*/ pNode->MoveTo(aPos);
+/*N*/ ExtendBy(rNodeRect, nSize > 1 ? RCP_NONE : RCP_ARG);
+/*N*/ }
+/*N*/ }
+/*N*/ }
+
+
+SmNode * SmTableNode::GetLeftMost()
+{
+ return this;
+}
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmLineNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
+/*N*/ {
+/*N*/ SmNode::Prepare(rFormat, rDocShell);
+/*N*/
+/*N*/ //! wir verwenden hier den 'FNT_VARIABLE' Font, da er vom Ascent und Descent
+/*N*/ //! ia besser zum Rest der Formel passt als der 'FNT_MATH' Font.
+/*N*/ GetFont() = rFormat.GetFont(FNT_VARIABLE);
+/*N*/ Flags() |= FLG_FONT;
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmLineNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ // arranges all subnodes in one row with some extra space between
+/*N*/ {
+/*N*/ SmNode *pNode;
+/*N*/ USHORT nSize = GetNumSubNodes();
+/*N*/ USHORT i;
+/*N*/ for (i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ pNode->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ // provide an empty rectangle with alignment parameters for the "current"
+/*N*/ // font (in order to make "a^1 {}_2^3 a_4" work correct, that is, have the
+/*N*/ // same sub-/supscript positions.)
+/*N*/ //! be sure to use a character that has explicitly defined HiAttribut
+/*N*/ //! line in rect.cxx such as 'a' in order to make 'vec a' look same to
+/*N*/ //! 'vec {a}'.
+/*N*/ SmRect::operator = (SmRect(aTmpDev, &rFormat, C2S("a"),
+/*N*/ GetFont().GetBorderWidth()));
+/*N*/ // make sure that the rectangle occupies (almost) no space
+/*N*/ SetWidth(1);
+/*N*/ SetItalicSpaces(0, 0);
+/*N*/
+/*N*/ if (nSize < 1)
+/*N*/ return;
+/*N*/
+/*N*/ // make distance depend on font size
+/*N*/ long nDist = +(rFormat.GetDistance(DIS_HORIZONTAL)
+/*N*/ * GetFont().GetSize().Height()) / 100L;
+/*N*/
+/*N*/ Point aPos;
+/*N*/ for (i = 0; i < nSize; i++)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ {
+/*N*/ aPos = pNode->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
+/*N*/
+/*N*/ // no horizontal space before first node
+/*N*/ if (i)
+/*N*/ aPos.X() += nDist;
+/*N*/
+/*N*/ pNode->MoveTo(aPos);
+/*N*/ ExtendBy( *pNode, RCP_XOR );
+/*N*/ }
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmExpressionNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ // as 'SmLineNode::Arrange' but keeps alignment of leftmost subnode
+/*N*/ {
+/*N*/ DBG_ASSERT(GetNumSubNodes() > 0, "Sm: keine subnodes");
+/*N*/
+/*N*/ SmLineNode::Arrange(rDev, rFormat);
+/*N*/
+/*N*/ // copy alignment of leftmost subnode if any
+/*N*/ SmNode *pNode = GetLeftMost();
+/*N*/ if (pNode)
+/*N*/ SetRectHorAlign(pNode->GetRectHorAlign(), FALSE);
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmUnHorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ BOOL bIsPostfix = GetToken().eType == TFACT;
+/*N*/
+/*N*/ SmNode *pOper = GetSubNode(bIsPostfix ? 1 : 0),
+/*N*/ *pBody = GetSubNode(bIsPostfix ? 0 : 1);
+/*N*/ DBG_ASSERT(pOper, "Sm: NULL pointer");
+/*N*/ DBG_ASSERT(pBody, "Sm: NULL pointer");
+/*N*/
+/*N*/ pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100));
+/*N*/ pOper->Arrange(rDev, rFormat);
+/*N*/ pBody->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ Point aPos = pOper->AlignTo(*pBody, bIsPostfix ? RP_RIGHT : RP_LEFT,
+/*N*/ RHA_CENTER, RVA_BASELINE);
+/*N*/ // add a bit space between operator and argument
+/*N*/ // (worst case -{1 over 2} where - and over have almost no space inbetween)
+/*N*/ long nDelta = pOper->GetFont().GetSize().Height() / 20;
+/*N*/ if (bIsPostfix)
+/*N*/ aPos.X() += nDelta;
+/*N*/ else
+/*N*/ aPos.X() -= nDelta;
+/*N*/ pOper->MoveTo(aPos);
+/*N*/
+/*N*/ SmRect::operator = (*pBody);
+/*N*/ long nOldBot = GetBottom();
+/*N*/
+/*N*/ ExtendBy(*pOper, RCP_XOR);
+/*N*/
+/*N*/ // workaround for Bug 50865: "a^2 a^+2" have different baselines
+/*N*/ // for exponents (if size of exponent is large enough)
+/*N*/ SetBottom(nOldBot);
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmRootNode::GetHeightVerOffset(const SmRect &rRect,
+/*N*/ long &rHeight, long &rVerOffset) const
+/*N*/ // calculate height and vertical offset of root sign suitable for 'rRect'
+/*N*/ {
+/*N*/ rVerOffset = (rRect.GetBottom() - rRect.GetAlignB()) / 2;
+/*N*/ rHeight = rRect.GetHeight() - rVerOffset;
+/*N*/
+/*N*/ DBG_ASSERT(rHeight >= 0, "Sm : Ooops...");
+/*N*/ DBG_ASSERT(rVerOffset >= 0, "Sm : Ooops...");
+/*N*/ }
+
+
+/*N*/ Point SmRootNode::GetExtraPos(const SmRect &rRootSymbol,
+/*N*/ const SmRect &rExtra) const
+/*N*/ {
+/*N*/ const Size &rSymSize = rRootSymbol.GetSize();
+/*N*/
+/*N*/ Point aPos = rRootSymbol.GetTopLeft()
+/*N*/ + Point((rSymSize.Width() * 70) / 100,
+/*N*/ (rSymSize.Height() * 52) / 100);
+/*N*/
+/*N*/ // from this calculate topleft edge of 'rExtra'
+/*N*/ aPos.X() -= rExtra.GetWidth() + rExtra.GetItalicRightSpace();
+/*N*/ aPos.Y() -= rExtra.GetHeight();
+/*N*/ // if there's enough space move a bit less to the right
+/*N*/ // examples: "nroot i a", "nroot j a"
+/*N*/ // (it looks better if we don't use italic-spaces here)
+/*N*/ long nX = rRootSymbol.GetLeft() + (rSymSize.Width() * 30) / 100;
+/*N*/ if (aPos.X() > nX)
+/*?*/ aPos.X() = nX;
+/*N*/
+/*N*/ return aPos;
+/*N*/ }
+
+
+/*N*/ void SmRootNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ //! pExtra needs to have the smaller index than pRootSym in order to
+/*N*/ //! not to get the root symbol but the pExtra when clicking on it in the
+/*N*/ //! GraphicWindow. (That is because of the simplicity of the algorithm
+/*N*/ //! that finds the node corresponding to a mouseclick in the window.)
+/*N*/ SmNode *pExtra = GetSubNode(0),
+/*N*/ *pRootSym = GetSubNode(1),
+/*N*/ *pBody = GetSubNode(2);
+/*N*/ DBG_ASSERT(pRootSym, "Sm: NULL pointer");
+/*N*/ DBG_ASSERT(pBody, "Sm: NULL pointer");
+/*N*/
+/*N*/ pBody->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ long nHeight,
+/*N*/ nVerOffset;
+/*N*/ GetHeightVerOffset(*pBody, nHeight, nVerOffset);
+/*N*/ nHeight += rFormat.GetDistance(DIS_ROOT)
+/*N*/ * GetFont().GetSize().Height() / 100L;
+/*N*/
+/*N*/ // font specialist advised to change the width first
+/*N*/ pRootSym->AdaptToY(rDev, nHeight);
+/*N*/ pRootSym->AdaptToX(rDev, pBody->GetItalicWidth());
+/*N*/
+/*N*/ pRootSym->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ Point aPos = pRootSym->AlignTo(*pBody, RP_LEFT, RHA_CENTER, RVA_BASELINE);
+/*N*/ //! overrride calulated vertical position
+/*N*/ aPos.Y() = pRootSym->GetTop() + pBody->GetBottom() - pRootSym->GetBottom();
+/*N*/ aPos.Y() -= nVerOffset;
+/*N*/ pRootSym->MoveTo(aPos);
+/*N*/
+/*N*/ if (pExtra)
+/*N*/ { pExtra->SetSize(Fraction(rFormat.GetRelSize(SIZ_INDEX), 100));
+/*N*/ pExtra->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ aPos = GetExtraPos(*pRootSym, *pExtra);
+/*N*/ pExtra->MoveTo(aPos);
+/*N*/ }
+/*N*/
+/*N*/ SmRect::operator = (*pBody);
+/*N*/ ExtendBy(*pRootSym, RCP_THIS);
+/*N*/ if (pExtra)
+/*N*/ ExtendBy(*pExtra, RCP_THIS, (BOOL) TRUE);
+/*N*/ }
+
+
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmBinHorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ SmNode *pLeft = GetSubNode(0),
+/*N*/ *pOper = GetSubNode(1),
+/*N*/ *pRight = GetSubNode(2);
+/*N*/ DBG_ASSERT(pLeft != NULL, "Sm: NULL pointer");
+/*N*/ DBG_ASSERT(pOper != NULL, "Sm: NULL pointer");
+/*N*/ DBG_ASSERT(pRight != NULL, "Sm: NULL pointer");
+/*N*/
+/*N*/ pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100));
+/*N*/
+/*N*/ pLeft ->Arrange(rDev, rFormat);
+/*N*/ pOper ->Arrange(rDev, rFormat);
+/*N*/ pRight->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ const SmRect &rOpRect = pOper->GetRect();
+/*N*/
+/*N*/ long nDist = (rOpRect.GetWidth() *
+/*N*/ rFormat.GetDistance(DIS_HORIZONTAL)) / 100L;
+/*N*/
+/*N*/ SmRect::operator = (*pLeft);
+/*N*/
+/*N*/ Point aPos;
+/*N*/ aPos = pOper->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
+/*N*/ aPos.X() += nDist;
+/*N*/ pOper->MoveTo(aPos);
+/*N*/ ExtendBy(*pOper, RCP_XOR);
+/*N*/
+/*N*/ aPos = pRight->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
+/*N*/ aPos.X() += nDist;
+/*N*/
+/*N*/ pRight->MoveTo(aPos);
+/*N*/ ExtendBy(*pRight, RCP_XOR);
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmBinVerNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ SmNode *pNum = GetSubNode(0),
+/*N*/ *pLine = GetSubNode(1),
+/*N*/ *pDenom = GetSubNode(2);
+/*N*/ DBG_ASSERT(pNum, "Sm : NULL pointer");
+/*N*/ DBG_ASSERT(pLine, "Sm : NULL pointer");
+/*N*/ DBG_ASSERT(pDenom, "Sm : NULL pointer");
+/*N*/
+/*N*/ BOOL bIsTextmode = rFormat.IsTextmode();
+/*N*/ if (bIsTextmode)
+/*N*/ {
+/*?*/ Fraction aFraction(rFormat.GetRelSize(SIZ_INDEX), 100);
+/*?*/ pNum ->SetSize(aFraction);
+/*?*/ pLine ->SetSize(aFraction);
+/*?*/ pDenom->SetSize(aFraction);
+/*N*/ }
+/*N*/
+/*N*/ pNum ->Arrange(rDev, rFormat);
+/*N*/ pDenom->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ long nFontHeight = GetFont().GetSize().Height(),
+/*N*/ nExtLen = nFontHeight * rFormat.GetDistance(DIS_FRACTION) / 100L,
+/*N*/ nThick = nFontHeight * rFormat.GetDistance(DIS_STROKEWIDTH) / 100L,
+/*N*/ nWidth = Max(pNum->GetItalicWidth(), pDenom->GetItalicWidth()),
+/*N*/ nNumDist = bIsTextmode ? 0 :
+/*N*/ nFontHeight * rFormat.GetDistance(DIS_NUMERATOR) / 100L,
+/*N*/ nDenomDist = bIsTextmode ? 0 :
+/*N*/ nFontHeight * rFormat.GetDistance(DIS_DENOMINATOR) / 100L;
+/*N*/
+ // font specialist advised to change the width first
+/*N*/ pLine->AdaptToY(rDev, nThick);
+/*N*/ pLine->AdaptToX(rDev, nWidth + 2 * nExtLen);
+/*N*/ pLine->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ // get horizontal alignment for numerator
+/*N*/ const SmNode *pLM = pNum->GetLeftMost();
+/*N*/ RectHorAlign eHorAlign = pLM->GetRectHorAlign();
+/*N*/
+/*N*/ // move numerator to its position
+/*N*/ Point aPos = pNum->AlignTo(*pLine, RP_TOP, eHorAlign, RVA_BASELINE);
+/*N*/ aPos.Y() -= nNumDist;
+/*N*/ pNum->MoveTo(aPos);
+/*N*/
+/*N*/ // get horizontal alignment for denominator
+/*N*/ pLM = pDenom->GetLeftMost();
+/*N*/ eHorAlign = pLM->GetRectHorAlign();
+/*N*/
+/*N*/ // move denominator to its position
+/*N*/ aPos = pDenom->AlignTo(*pLine, RP_BOTTOM, eHorAlign, RVA_BASELINE);
+/*N*/ aPos.Y() += nDenomDist;
+/*N*/ pDenom->MoveTo(aPos);
+/*N*/
+/*N*/ SmRect::operator = (*pNum);
+/*N*/ ExtendBy(*pDenom, RCP_NONE).ExtendBy(*pLine, RCP_NONE, pLine->GetCenterY());
+/*N*/ }
+
+
+
+/*N*/ SmNode * SmBinVerNode::GetLeftMost()
+/*N*/ {
+/*N*/ return this;
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+double Det(const Point &rHeading1, const Point &rHeading2)
+ // gibt den Wert der durch die beiden Punkte gebildeten Determinante
+ // zurueck
+{
+ return rHeading1.X() * rHeading2.Y() - rHeading1.Y() * rHeading2.X();
+}
+
+
+BOOL IsPointInLine(const Point &rPoint1,
+ const Point &rPoint2, const Point &rHeading2)
+ // ergibt TRUE genau dann, wenn der Punkt 'rPoint1' zu der Gerade gehoert die
+ // durch den Punkt 'rPoint2' geht und den Richtungsvektor 'rHeading2' hat
+{
+ DBG_ASSERT(rHeading2 != Point(), "Sm : 0 vector");
+
+ BOOL bRes = FALSE;
+ const double eps = 5.0 * DBL_EPSILON;
+
+ double fLambda;
+ if (labs(rHeading2.X()) > labs(rHeading2.Y()))
+ {
+ fLambda = (rPoint1.X() - rPoint2.X()) / (double) rHeading2.X();
+ bRes = fabs(rPoint1.Y() - (rPoint2.Y() + fLambda * rHeading2.Y())) < eps;
+ }
+ else
+ {
+ fLambda = (rPoint1.Y() - rPoint2.Y()) / (double) rHeading2.Y();
+ bRes = fabs(rPoint1.X() - (rPoint2.X() + fLambda * rHeading2.X())) < eps;
+ }
+
+ return bRes;
+}
+
+
+USHORT GetLineIntersectionPoint(Point &rResult,
+ const Point& rPoint1, const Point &rHeading1,
+ const Point& rPoint2, const Point &rHeading2)
+{
+ DBG_ASSERT(rHeading1 != Point(), "Sm : 0 vector");
+ DBG_ASSERT(rHeading2 != Point(), "Sm : 0 vector");
+
+ USHORT nRes = 1;
+ const double eps = 5.0 * DBL_EPSILON;
+
+ // sind die Richtumgsvektoren linear abhaengig ?
+ double fDet = Det(rHeading1, rHeading2);
+ if (fabs(fDet) < eps)
+ {
+ nRes = IsPointInLine(rPoint1, rPoint2, rHeading2) ? USHRT_MAX : 0;
+ rResult = nRes ? rPoint1 : Point();
+ }
+ else
+ {
+ // hier achten wir nicht auf Rechengenauigkeit
+ // (das wuerde aufwendiger und lohnt sich hier kaum)
+ double fLambda = ( (rPoint1.Y() - rPoint2.Y()) * rHeading2.X()
+ - (rPoint1.X() - rPoint2.X()) * rHeading2.Y())
+ / fDet;
+ rResult = Point(rPoint1.X() + (long) (fLambda * rHeading1.X()),
+ rPoint1.Y() + (long) (fLambda * rHeading1.Y()));
+ }
+
+ return nRes;
+}
+
+
+
+SmBinDiagonalNode::SmBinDiagonalNode(const SmToken &rNodeToken)
+: SmStructureNode(NBINDIAGONAL, rNodeToken)
+{
+ bAscending = FALSE;
+ SetNumSubNodes(3);
+}
+
+
+void SmBinDiagonalNode::GetOperPosSize(Point &rPos, Size &rSize,
+ const Point &rDiagPoint, double fAngleDeg) const
+ // gibt die Position und Groesse fuer den Diagonalstrich zurueck.
+ // Vor.: das SmRect des Nodes gibt die Begrenzung vor(!), muss also selbst
+ // bereits bekannt sein.
+
+{
+ const double fPi = 3.1415926535897932384626433;
+ double fAngleRad = fAngleDeg / 180.0 * fPi;
+ long nRectLeft = GetItalicLeft(),
+ nRectRight = GetItalicRight(),
+ nRectTop = GetTop(),
+ nRectBottom = GetBottom();
+ Point aRightHdg (100, 0),
+ aDownHdg (0, 100),
+ aDiagHdg ( (long)(100.0 * cos(fAngleRad)),
+ (long)(-100.0 * sin(fAngleRad)) );
+
+ long nLeft, nRight, nTop, nBottom; // Raender des Rechtecks fuer die
+ // Diagonale
+ Point aPoint;
+ if (IsAscending())
+ {
+ //
+ // obere rechte Ecke bestimmen
+ //
+ GetLineIntersectionPoint(aPoint,
+ Point(nRectLeft, nRectTop), aRightHdg,
+ rDiagPoint, aDiagHdg);
+ //
+ // gibt es einen Schnittpunkt mit dem oberen Rand ?
+ if (aPoint.X() <= nRectRight)
+ {
+ nRight = aPoint.X();
+ nTop = nRectTop;
+ }
+ else
+ {
+ // es mu?einen Schnittpunkt mit dem rechten Rand geben!
+ GetLineIntersectionPoint(aPoint,
+ Point(nRectRight, nRectTop), aDownHdg,
+ rDiagPoint, aDiagHdg);
+
+ nRight = nRectRight;
+ nTop = aPoint.Y();
+ }
+
+ //
+ // untere linke Ecke bestimmen
+ //
+ GetLineIntersectionPoint(aPoint,
+ Point(nRectLeft, nRectBottom), aRightHdg,
+ rDiagPoint, aDiagHdg);
+ //
+ // gibt es einen Schnittpunkt mit dem unteren Rand ?
+ if (aPoint.X() >= nRectLeft)
+ {
+ nLeft = aPoint.X();
+ nBottom = nRectBottom;
+ }
+ else
+ {
+ // es mu?einen Schnittpunkt mit dem linken Rand geben!
+ GetLineIntersectionPoint(aPoint,
+ Point(nRectLeft, nRectTop), aDownHdg,
+ rDiagPoint, aDiagHdg);
+
+ nLeft = nRectLeft;
+ nBottom = aPoint.Y();
+ }
+ }
+ else
+ {
+ //
+ // obere linke Ecke bestimmen
+ //
+ GetLineIntersectionPoint(aPoint,
+ Point(nRectLeft, nRectTop), aRightHdg,
+ rDiagPoint, aDiagHdg);
+ //
+ // gibt es einen Schnittpunkt mit dem oberen Rand ?
+ if (aPoint.X() >= nRectLeft)
+ {
+ nLeft = aPoint.X();
+ nTop = nRectTop;
+ }
+ else
+ {
+ // es mu?einen Schnittpunkt mit dem linken Rand geben!
+ GetLineIntersectionPoint(aPoint,
+ Point(nRectLeft, nRectTop), aDownHdg,
+ rDiagPoint, aDiagHdg);
+
+ nLeft = nRectLeft;
+ nTop = aPoint.Y();
+ }
+
+ //
+ // untere rechte Ecke bestimmen
+ //
+ GetLineIntersectionPoint(aPoint,
+ Point(nRectLeft, nRectBottom), aRightHdg,
+ rDiagPoint, aDiagHdg);
+ //
+ // gibt es einen Schnittpunkt mit dem unteren Rand ?
+ if (aPoint.X() <= nRectRight)
+ {
+ nRight = aPoint.X();
+ nBottom = nRectBottom;
+ }
+ else
+ {
+ // es mu?einen Schnittpunkt mit dem rechten Rand geben!
+ GetLineIntersectionPoint(aPoint,
+ Point(nRectRight, nRectTop), aDownHdg,
+ rDiagPoint, aDiagHdg);
+
+ nRight = nRectRight;
+ nBottom = aPoint.Y();
+ }
+ }
+
+ rSize = Size(nRight - nLeft + 1, nBottom - nTop + 1);
+ rPos.X() = nLeft;
+ rPos.Y() = nTop;
+}
+
+
+void SmBinDiagonalNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+{
+ //! die beiden Argumente muessen in den Subnodes vor dem Operator kommen,
+ //! damit das anklicken im GraphicWindow den FormulaCursor richtig setzt
+ //! (vgl SmRootNode)
+ SmNode *pLeft = GetSubNode(0),
+ *pRight = GetSubNode(1);
+ DBG_ASSERT(pLeft, "Sm : NULL pointer");
+ DBG_ASSERT(pRight, "Sm : NULL pointer");
+
+ DBG_ASSERT(GetSubNode(2)->GetType() == NPOLYLINE, "Sm : falscher Nodetyp");
+ SmPolyLineNode *pOper = (SmPolyLineNode *) GetSubNode(2);
+ DBG_ASSERT(pOper, "Sm : NULL pointer");
+
+ //! some routines being called extract some info from the OutputDevice's
+ //! font (eg the space to be used for borders OR the font name(!!)).
+ //! Thus the font should reflect the needs and has to be set!
+ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+ aTmpDev.SetFont(GetFont());
+
+ pLeft->Arrange(aTmpDev, rFormat);
+ pRight->Arrange(aTmpDev, rFormat);
+
+ // implizit die Weite (incl Rand) des Diagonalstrichs ermitteln
+ pOper->Arrange(aTmpDev, rFormat);
+
+ long nDelta = pOper->GetWidth() * 8 / 10;
+
+ // TopLeft Position vom rechten Argument ermitteln
+ Point aPos;
+ aPos.X() = pLeft->GetItalicRight() + nDelta + pRight->GetItalicLeftSpace();
+ if (IsAscending())
+ aPos.Y() = pLeft->GetBottom() + nDelta;
+ else
+ aPos.Y() = pLeft->GetTop() - nDelta - pRight->GetHeight();
+
+ pRight->MoveTo(aPos);
+
+ // neue Baseline bestimmen
+ long nBaseline = IsAscending() ? (pLeft->GetBottom() + pRight->GetTop()) / 2
+ : (pLeft->GetTop() + pRight->GetBottom()) / 2;
+ Point aLogCenter ((pLeft->GetItalicRight() + pRight->GetItalicLeft()) / 2,
+ nBaseline);
+
+ SmRect::operator = (*pLeft);
+ ExtendBy(*pRight, RCP_NONE);
+
+
+ // Position und Groesse des Diagonalstrich ermitteln
+ Size aSize;
+ GetOperPosSize(aPos, aSize, aLogCenter, IsAscending() ? 60.0 : -60.0);
+
+ // font specialist advised to change the width first
+ pOper->AdaptToY(aTmpDev, aSize.Height());
+ pOper->AdaptToX(aTmpDev, aSize.Width());
+ // und diese wirksam machen
+ pOper->Arrange(aTmpDev, rFormat);
+
+ pOper->MoveTo(aPos);
+
+ ExtendBy(*pOper, RCP_NONE, nBaseline);
+}
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmSubSupNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ DBG_ASSERT(GetNumSubNodes() == 1 + SUBSUP_NUM_ENTRIES,
+/*N*/ "Sm: falsche Anzahl von subnodes");
+/*N*/
+/*N*/ SmNode *pBody = GetBody();
+/*N*/ DBG_ASSERT(pBody, "Sm: NULL pointer");
+/*N*/
+/*N*/ long nOrigHeight = pBody->GetFont().GetSize().Height();
+/*N*/
+/*N*/ pBody->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ const SmRect &rBodyRect = pBody->GetRect();
+/*N*/ SmRect::operator = (rBodyRect);
+/*N*/
+/*N*/ // line that separates sub- and supscript rectangles
+/*N*/ long nDelimLine = SmFromTo(GetAlignB(), GetAlignT(), 0.4);
+/*N*/
+/*N*/ Point aPos;
+/*N*/ long nDelta, nDist;
+/*N*/
+/*N*/ // iterate over all possible sub-/supscripts
+/*N*/ SmRect aTmpRect (rBodyRect);
+/*N*/ for (int i = 0; i < SUBSUP_NUM_ENTRIES; i++)
+/*N*/ { SmSubSup eSubSup = (SmSubSup) i; // cast
+/*N*/ SmNode *pSubSup = GetSubSup(eSubSup);
+/*N*/
+/*N*/ if (!pSubSup)
+/*N*/ continue;
+/*N*/
+/*N*/ // switch position of limits if we are in textmode
+/*N*/ if (rFormat.IsTextmode() && (GetToken().nGroup & TGLIMIT))
+/*N*/ switch (eSubSup)
+/*?*/ { case CSUB: eSubSup = RSUB; break;
+/*?*/ case CSUP: eSubSup = RSUP; break;
+/*N*/ }
+/*N*/
+/*N*/ // prevent sub-/supscripts from diminishing in size
+/*N*/ // (as would be in "a_{1_{2_{3_4}}}")
+/*N*/ if (GetFont().GetSize().Height() > rFormat.GetBaseSize().Height() / 3)
+/*N*/ {
+/*N*/ USHORT nIndex = (eSubSup == CSUB || eSubSup == CSUP) ?
+/*N*/ SIZ_LIMITS : SIZ_INDEX;
+/*N*/ Fraction aFraction ( rFormat.GetRelSize(nIndex), 100 );
+/*N*/ pSubSup->SetSize(aFraction);
+/*N*/ }
+/*N*/
+/*N*/ pSubSup->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ BOOL bIsTextmode = rFormat.IsTextmode();
+/*N*/ nDist = 0;
+/*N*/
+/*N*/ //! be sure that CSUB, CSUP are handled before the other cases!
+/*N*/ switch (eSubSup)
+/*N*/ { case RSUB :
+/*N*/ case LSUB :
+/*N*/ if (!bIsTextmode)
+/*N*/ nDist = nOrigHeight
+/*N*/ * rFormat.GetDistance(DIS_SUBSCRIPT) / 100L;
+/*N*/ aPos = pSubSup->GetRect().AlignTo(aTmpRect,
+/*N*/ eSubSup == LSUB ? RP_LEFT : RP_RIGHT,
+/*N*/ RHA_CENTER, RVA_BOTTOM);
+/*N*/ aPos.Y() += nDist;
+/*N*/ nDelta = nDelimLine - aPos.Y();
+/*N*/ if (nDelta > 0)
+/*N*/ aPos.Y() += nDelta;
+/*N*/ break;
+/*N*/ case RSUP :
+/*N*/ case LSUP :
+/*N*/ if (!bIsTextmode)
+/*N*/ nDist = nOrigHeight
+/*N*/ * rFormat.GetDistance(DIS_SUPERSCRIPT) / 100L;
+/*N*/ aPos = pSubSup->GetRect().AlignTo(aTmpRect,
+/*N*/ eSubSup == LSUP ? RP_LEFT : RP_RIGHT,
+/*N*/ RHA_CENTER, RVA_TOP);
+/*N*/ aPos.Y() -= nDist;
+/*N*/ nDelta = aPos.Y() + pSubSup->GetHeight() - nDelimLine;
+/*N*/ if (nDelta > 0)
+/*?*/ aPos.Y() -= nDelta;
+/*N*/ break;
+/*N*/ case CSUB :
+/*N*/ if (!bIsTextmode)
+/*N*/ nDist = nOrigHeight
+/*N*/ * rFormat.GetDistance(DIS_LOWERLIMIT) / 100L;
+/*N*/ aPos = pSubSup->GetRect().AlignTo(rBodyRect, RP_BOTTOM,
+/*N*/ RHA_CENTER, RVA_BASELINE);
+/*N*/ aPos.Y() += nDist;
+/*N*/ break;
+/*N*/ case CSUP :
+/*N*/ if (!bIsTextmode)
+/*N*/ nDist = nOrigHeight
+/*N*/ * rFormat.GetDistance(DIS_UPPERLIMIT) / 100L;
+/*N*/ aPos = pSubSup->GetRect().AlignTo(rBodyRect, RP_TOP,
+/*N*/ RHA_CENTER, RVA_BASELINE);
+/*N*/ aPos.Y() -= nDist;
+/*N*/ break;
+/*N*/ default :
+/*N*/ DBG_ASSERT(FALSE, "Sm: unbekannter Fall");
+/*N*/ }
+/*N*/
+/*N*/ pSubSup->MoveTo(aPos);
+/*N*/ ExtendBy(*pSubSup, RCP_THIS, (BOOL) TRUE);
+/*N*/
+/*N*/ // update rectangle to which RSUB, RSUP, LSUB, LSUP
+/*N*/ // will be aligned to
+/*N*/ if (eSubSup == CSUB || eSubSup == CSUP)
+/*N*/ aTmpRect = *this;
+/*N*/ }
+/*N*/ }
+
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmBraceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ SmNode *pLeft = GetSubNode(0),
+/*N*/ *pBody = GetSubNode(1),
+/*N*/ *pRight = GetSubNode(2);
+/*N*/ DBG_ASSERT(pLeft, "Sm: NULL pointer");
+/*N*/ DBG_ASSERT(pBody, "Sm: NULL pointer");
+/*N*/ DBG_ASSERT(pRight, "Sm: NULL pointer");
+/*N*/
+/*N*/ pBody->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ BOOL bIsScaleNormal = rFormat.IsScaleNormalBrackets(),
+/*N*/ bScale = pBody->GetHeight() > 0 &&
+/*N*/ (GetScaleMode() == SCALE_HEIGHT || bIsScaleNormal),
+/*N*/ bIsABS = GetToken().eType == TABS;
+/*N*/
+/*N*/ long nFaceHeight = GetFont().GetSize().Height();
+/*N*/
+/*N*/ // Uebergroesse in % ermitteln
+/*N*/ USHORT nPerc = 0;
+/*N*/ if (!bIsABS && bScale)
+/*N*/ { // im Fall von Klammern mit Uebergroesse...
+/*N*/ int nIndex = GetScaleMode() == SCALE_HEIGHT ?
+/*N*/ DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE;
+/*N*/ nPerc = rFormat.GetDistance(nIndex);
+/*N*/ }
+/*N*/
+/*N*/ // ermitteln der Hoehe fuer die Klammern
+/*N*/ long nBraceHeight;
+/*N*/ if (bScale)
+/*N*/ {
+/*N*/ nBraceHeight = pBody->GetType() == NBRACEBODY ?
+/*N*/ ((SmBracebodyNode *) pBody)->GetBodyHeight()
+/*N*/ : pBody->GetHeight();
+/*N*/ nBraceHeight += 2 * (nBraceHeight * nPerc / 100L);
+/*N*/ }
+/*N*/ else
+/*N*/ nBraceHeight = nFaceHeight;
+/*N*/
+/*N*/ // Abstand zum Argument
+/*N*/ nPerc = bIsABS ? 0 : rFormat.GetDistance(DIS_BRACKETSPACE);
+/*N*/ long nDist = nFaceHeight * nPerc / 100L;
+/*N*/
+/*N*/ // sofern erwuenscht skalieren der Klammern auf die gewuenschte Groesse
+/*N*/ if (bScale)
+/*N*/ {
+/*N*/ Size aSize (pLeft->GetFont().GetSize());
+/*N*/ DBG_ASSERT(pRight->GetFont().GetSize() == aSize,
+/*N*/ "Sm : unterschiedliche Fontgroessen");
+/*N*/ aSize.Width() = Min((long) nBraceHeight * 60L / 100L,
+/*N*/ rFormat.GetBaseSize().Height() * 3L / 2L);
+/*N*/ // correction factor since change from StarMath to StarSymbol font
+/*N*/ // because of the different font width in the FontMetric
+/*N*/ aSize.Width() *= 182;
+/*N*/ aSize.Width() /= 267;
+/*N*/
+/*N*/ xub_Unicode cChar = pLeft->GetToken().cMathChar;
+/*N*/ if (cChar != MS_LINE && cChar != MS_DLINE)
+/*N*/ pLeft ->GetFont().SetSize(aSize);
+/*N*/
+/*N*/ cChar = pRight->GetToken().cMathChar;
+/*N*/ if (cChar != MS_LINE && cChar != MS_DLINE)
+/*N*/ pRight->GetFont().SetSize(aSize);
+/*N*/
+/*N*/ pLeft ->AdaptToY(rDev, nBraceHeight);
+/*N*/ pRight->AdaptToY(rDev, nBraceHeight);
+/*N*/ }
+/*N*/
+/*N*/ pLeft ->Arrange(rDev, rFormat);
+/*N*/ pRight->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ // damit auch "\(a\) - (a) - left ( a right )" vernuenftig aussieht
+/*N*/ RectVerAlign eVerAlign = bScale ? RVA_CENTERY : RVA_BASELINE;
+/*N*/
+/*N*/ Point aPos;
+/*N*/ aPos = pLeft->AlignTo(*pBody, RP_LEFT, RHA_CENTER, eVerAlign);
+/*N*/ aPos.X() -= nDist;
+/*N*/ pLeft->MoveTo(aPos);
+/*N*/
+/*N*/ aPos = pRight->AlignTo(*pBody, RP_RIGHT, RHA_CENTER, eVerAlign);
+/*N*/ aPos.X() += nDist;
+/*N*/ pRight->MoveTo(aPos);
+/*N*/
+/*N*/ SmRect::operator = (*pBody);
+/*N*/ ExtendBy(*pLeft, RCP_THIS).ExtendBy(*pRight, RCP_THIS);
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmBracebodyNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ USHORT nNumSubNodes = GetNumSubNodes();
+/*N*/ if (nNumSubNodes == 0)
+/*N*/ return;
+/*N*/
+/*N*/ // arrange arguments
+/*N*/ USHORT i;
+/*N*/ for (i = 0; i < nNumSubNodes; i += 2)
+/*N*/ GetSubNode(i)->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ // build reference rectangle with necessary info for vertical alignment
+/*N*/ SmRect aRefRect (*GetSubNode(0));
+/*N*/ for (i = 0; i < nNumSubNodes; i += 2)
+/*N*/ {
+/*N*/ SmRect aTmpRect (*GetSubNode(i));
+/*N*/ Point aPos = aTmpRect.AlignTo(aRefRect, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
+/*N*/ aTmpRect.MoveTo(aPos);
+/*N*/ aRefRect.ExtendBy(aTmpRect, RCP_XOR);
+/*N*/ }
+/*N*/
+/*N*/ nBodyHeight = aRefRect.GetHeight();
+/*N*/
+/*N*/ // scale separators to required height and arrange them
+/*N*/ BOOL bScale = GetScaleMode() == SCALE_HEIGHT || rFormat.IsScaleNormalBrackets();
+/*N*/ long nHeight = bScale ? aRefRect.GetHeight() : GetFont().GetSize().Height();
+/*N*/ int nIndex = GetScaleMode() == SCALE_HEIGHT ?
+/*N*/ DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE;
+/*N*/ USHORT nPerc = rFormat.GetDistance(nIndex);
+/*N*/ if (bScale)
+/*N*/ nHeight += 2 * (nHeight * nPerc / 100L);
+/*N*/ for (i = 1; i < nNumSubNodes; i += 2)
+/*N*/ {
+/*?*/ SmNode *pNode = GetSubNode(i);
+/*?*/ pNode->AdaptToY(rDev, nHeight);
+/*?*/ pNode->Arrange(rDev, rFormat);
+/*N*/ }
+/*N*/
+/*N*/ // horizontal distance between argument and brackets or separators
+/*N*/ long nDist = GetFont().GetSize().Height()
+/*N*/ * rFormat.GetDistance(DIS_BRACKETSPACE) / 100L;
+/*N*/
+/*N*/ SmNode *pLeft = GetSubNode(0);
+/*N*/ SmRect::operator = (*pLeft);
+/*N*/ for (i = 1; i < nNumSubNodes; i++)
+/*N*/ {
+/*?*/ BOOL bIsSeparator = i % 2 != 0;
+/*?*/ RectVerAlign eVerAlign = bIsSeparator ? RVA_CENTERY : RVA_BASELINE;
+/*?*/
+/*?*/ SmNode *pRight = GetSubNode(i);
+/*?*/ Point aPosX = pRight->AlignTo(*pLeft, RP_RIGHT, RHA_CENTER, eVerAlign),
+/*?*/ aPosY = pRight->AlignTo(aRefRect, RP_RIGHT, RHA_CENTER, eVerAlign);
+/*?*/ aPosX.X() += nDist;
+/*?*/
+/*?*/ pRight->MoveTo(Point(aPosX.X(), aPosY.Y()));
+/*?*/ ExtendBy(*pRight, bIsSeparator ? RCP_THIS : RCP_XOR);
+/*?*/
+/*?*/ pLeft = pRight;
+/*N*/ }
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+void SmVerticalBraceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+{
+ SmNode *pBody = GetSubNode(0),
+ *pBrace = GetSubNode(1),
+ *pScript = GetSubNode(2);
+ DBG_ASSERT(pBody, "Sm: NULL pointer!");
+ DBG_ASSERT(pBrace, "Sm: NULL pointer!");
+ DBG_ASSERT(pScript, "Sm: NULL pointer!");
+
+ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+ aTmpDev.SetFont(GetFont());
+
+ pBody->Arrange(aTmpDev, rFormat);
+
+ // Groesse wie bei Grenzen fuer diesen Teil
+ pScript->SetSize( Fraction( rFormat.GetRelSize(SIZ_LIMITS), 100 ) );
+ // etwas hoehere Klammern als normal
+ pBrace ->SetSize( Fraction(3, 2) );
+
+ long nItalicWidth = pBody->GetItalicWidth();
+ if (nItalicWidth > 0)
+ pBrace->AdaptToX(aTmpDev, nItalicWidth);
+
+ pBrace ->Arrange(aTmpDev, rFormat);
+ pScript->Arrange(aTmpDev, rFormat);
+
+ // die relativen Position und die Abstaende zueinander bestimmen
+ RectPos eRectPos;
+ long nFontHeight = pBody->GetFont().GetSize().Height();
+ long nDistBody = nFontHeight * rFormat.GetDistance(DIS_ORNAMENTSIZE),
+ nDistScript = nFontHeight;
+ if (GetToken().eType == TOVERBRACE)
+ {
+ eRectPos = RP_TOP;
+ nDistBody = - nDistBody;
+ nDistScript *= - rFormat.GetDistance(DIS_UPPERLIMIT);
+ }
+ else // TUNDERBRACE
+ {
+ eRectPos = RP_BOTTOM;
+ nDistScript *= + rFormat.GetDistance(DIS_LOWERLIMIT);
+ }
+ nDistBody /= 100L;
+ nDistScript /= 100L;
+
+ Point aPos = pBrace->AlignTo(*pBody, eRectPos, RHA_CENTER, RVA_BASELINE);
+ aPos.Y() += nDistBody;
+ pBrace->MoveTo(aPos);
+
+ aPos = pScript->AlignTo(*pBrace, eRectPos, RHA_CENTER, RVA_BASELINE);
+ aPos.Y() += nDistScript;
+ pScript->MoveTo(aPos);
+
+ SmRect::operator = (*pBody);
+ ExtendBy(*pBrace, RCP_THIS).ExtendBy(*pScript, RCP_THIS);
+}
+
+
+/**************************************************************************/
+
+#ifdef MAC
+#pragma segment FrmNode_03
+#endif
+
+
+/*N*/ SmNode * SmOperNode::GetSymbol()
+/*N*/ {
+/*N*/ SmNode *pNode = GetSubNode(0);
+/*N*/ DBG_ASSERT(pNode, "Sm: NULL pointer!");
+/*N*/
+/*N*/ if (pNode->GetType() == NSUBSUP)
+/*N*/ pNode = ((SmSubSupNode *) pNode)->GetBody();
+/*N*/
+/*N*/ DBG_ASSERT(pNode, "Sm: NULL pointer!");
+/*N*/ return pNode;
+/*N*/ }
+
+
+/*N*/ long SmOperNode::CalcSymbolHeight(const SmNode &rSymbol,
+/*N*/ const SmFormat &rFormat) const
+/*N*/ // returns the font height to be used for operator-symbol
+/*N*/ {
+/*N*/ long nHeight = GetFont().GetSize().Height();
+/*N*/
+/*N*/ SmTokenType eType = GetToken().eType;
+/*N*/ if (eType == TLIM || eType == TLIMINF || eType == TLIMSUP)
+/*N*/ return nHeight;
+/*N*/
+/*N*/ if (!rFormat.IsTextmode())
+/*N*/ {
+/*N*/ // set minimum size ()
+/*N*/ nHeight += (nHeight * 20L) / 100L;
+/*N*/
+/*N*/ nHeight += nHeight
+/*N*/ * rFormat.GetDistance(DIS_OPERATORSIZE) / 100L;
+/*N*/ nHeight = nHeight * 686L / 845L;
+/*N*/ }
+/*N*/
+/*N*/ // correct user-defined symbols to match height of sum from used font
+/*N*/ if (rSymbol.GetToken().eType == TSPECIAL)
+/*?*/ nHeight = nHeight * 845L / 686L;
+/*N*/
+/*N*/ return nHeight;
+/*N*/ }
+
+
+/*N*/ void SmOperNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ SmNode *pOper = GetSubNode(0);
+/*N*/ SmNode *pBody = GetSubNode(1);
+/*N*/
+/*N*/ DBG_ASSERT(pOper, "Sm: Subnode fehlt");
+/*N*/ DBG_ASSERT(pBody, "Sm: Subnode fehlt");
+/*N*/
+/*N*/ SmNode *pSymbol = GetSymbol();
+/*N*/ pSymbol->SetSize(Fraction(CalcSymbolHeight(*pSymbol, rFormat),
+/*N*/ pSymbol->GetFont().GetSize().Height()));
+/*N*/
+/*N*/ pBody->Arrange(rDev, rFormat);
+/*N*/ pOper->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ long nOrigHeight = GetFont().GetSize().Height(),
+/*N*/ nDist = nOrigHeight
+/*N*/ * rFormat.GetDistance(DIS_OPERATORSPACE) / 100L;
+/*N*/
+/*N*/ Point aPos = pOper->AlignTo(*pBody, RP_LEFT, RHA_CENTER, /*RVA_CENTERY*/RVA_MID);
+/*N*/ aPos.X() -= nDist;
+/*N*/ pOper->MoveTo(aPos);
+/*N*/
+/*N*/ SmRect::operator = (*pBody);
+/*N*/ ExtendBy(*pOper, RCP_THIS);
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+void SmAlignNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+ // setzt im ganzen subtree (incl aktuellem node) das alignment
+{
+ DBG_ASSERT(GetNumSubNodes() > 0, "Sm: SubNode fehlt");
+
+ SmNode *pNode = GetSubNode(0);
+
+ RectHorAlign eHorAlign = RHA_CENTER;
+ switch (GetToken().eType)
+ {
+ case TALIGNL: eHorAlign = RHA_LEFT; break;
+ case TALIGNC: eHorAlign = RHA_CENTER; break;
+ case TALIGNR: eHorAlign = RHA_RIGHT; break;
+ }
+ SetRectHorAlign(eHorAlign);
+
+ pNode->Arrange(rDev, rFormat);
+
+ SmRect::operator = (pNode->GetRect());
+}
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmAttributNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ SmNode *pAttr = GetSubNode(0),
+/*N*/ *pBody = GetSubNode(1);
+/*N*/ DBG_ASSERT(pBody, "Sm: Body fehlt");
+/*N*/ DBG_ASSERT(pAttr, "Sm: Attribut fehlt");
+/*N*/
+/*N*/ pBody->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ if (GetScaleMode() == SCALE_WIDTH)
+/*?*/ pAttr->AdaptToX(rDev, pBody->GetItalicWidth());
+/*N*/ pAttr->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ // get relative position of attribut
+/*N*/ RectVerAlign eVerAlign;
+/*N*/ long nDist = 0;
+/*N*/ switch (GetToken().eType)
+/*N*/ { case TUNDERLINE :
+/*?*/ eVerAlign = RVA_ATTRIBUT_LO;
+/*?*/ break;
+/*N*/ case TOVERSTRIKE :
+/*?*/ eVerAlign = RVA_ATTRIBUT_MID;
+/*?*/ break;
+/*N*/ default :
+/*N*/ eVerAlign = RVA_ATTRIBUT_HI;
+/*N*/ if (pBody->GetType() == NATTRIBUT)
+/*?*/ nDist = GetFont().GetSize().Height()
+/*?*/ * rFormat.GetDistance(DIS_ORNAMENTSPACE) / 100L;
+/*N*/ }
+/*N*/ Point aPos = pAttr->AlignTo(*pBody, RP_ATTRIBUT, RHA_CENTER, eVerAlign);
+/*N*/ aPos.Y() -= nDist;
+/*N*/ pAttr->MoveTo(aPos);
+/*N*/
+/*N*/ SmRect::operator = (*pBody);
+/*N*/ ExtendBy(*pAttr, RCP_THIS, (BOOL) TRUE);
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+
+
+
+
+/*N*/ void SmFontNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
+/*N*/ {
+/*N*/ //! prepare subnodes first
+/*N*/ SmNode::Prepare(rFormat, rDocShell);
+/*N*/
+/*N*/ int nFnt = -1;
+/*N*/ switch (GetToken().eType)
+/*N*/ {
+/*?*/ case TFIXED: nFnt = FNT_FIXED; break;
+/*N*/ case TSANS: nFnt = FNT_SANS; break;
+/*?*/ case TSERIF: nFnt = FNT_SERIF; break;
+/*N*/ }
+/*N*/ if (nFnt != -1)
+/*N*/ { GetFont() = rFormat.GetFont(nFnt);
+/*N*/ SetFont(GetFont());
+/*N*/ }
+/*N*/
+/*N*/ //! prevent overwrites of this font by 'Arrange' or 'SetFont' calls of
+/*N*/ //! other font nodes (those with lower depth in the tree)
+/*N*/ Flags() |= FLG_FONT;
+/*N*/ }
+
+
+/*N*/ void SmFontNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ SmNode *pNode = GetSubNode(1);
+/*N*/ DBG_ASSERT(pNode, "Sm: SubNode fehlt");
+/*N*/
+/*N*/ switch (GetToken().eType)
+/*N*/ { case TSIZE :
+/*N*/ pNode->SetFontSize(aFontSize, nSizeType);
+/*N*/ break;
+/*N*/ case TSANS :
+/*N*/ case TSERIF :
+/*N*/ case TFIXED :
+/*N*/ pNode->SetFont(GetFont());
+/*N*/ break;
+/*N*/ case TUNKNOWN : break; // no assertion on "font <?> <?>"
+/*N*/
+/*?*/ case TPHANTOM : SetPhantom(TRUE); break;
+/*N*/ case TBOLD : SetAttribut(ATTR_BOLD); break;
+/*N*/ case TITALIC : SetAttribut(ATTR_ITALIC); break;
+/*?*/ case TNBOLD : ClearAttribut(ATTR_BOLD); break;
+/*N*/ case TNITALIC : ClearAttribut(ATTR_ITALIC); break;
+/*N*/
+/*?*/ case TBLACK : SetColor(Color(COL_BLACK)); break;
+/*?*/ case TWHITE : SetColor(Color(COL_WHITE)); break;
+/*?*/ case TRED : SetColor(Color(COL_RED)); break;
+/*?*/ case TGREEN : SetColor(Color(COL_GREEN)); break;
+/*?*/ case TBLUE : SetColor(Color(COL_BLUE)); break;
+/*?*/ case TCYAN : SetColor(Color(COL_CYAN)); break;
+/*?*/ case TMAGENTA : SetColor(Color(COL_MAGENTA)); break;
+/*?*/ case TYELLOW : SetColor(Color(COL_YELLOW)); break;
+/*N*/
+/*N*/ default:
+/*?*/ DBG_ASSERT(FALSE, "Sm: unbekannter Fall");
+/*N*/ }
+/*N*/
+/*N*/ pNode->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ SmRect::operator = (pNode->GetRect());
+/*N*/ }
+
+
+/*N*/ void SmFontNode::SetSizeParameter(const Fraction& rValue, USHORT Type)
+/*N*/ {
+/*N*/ nSizeType = Type;
+/*N*/ aFontSize = rValue;
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ SmPolyLineNode::SmPolyLineNode(const SmToken &rNodeToken)
+/*N*/ : SmGraphicNode(NPOLYLINE, rNodeToken)
+/*N*/ {
+/*N*/ aPoly.SetSize(2);
+/*N*/ nWidth = 0;
+/*N*/ }
+
+
+/*N*/ void SmPolyLineNode::AdaptToX(const OutputDevice &rDev, ULONG nWidth)
+/*N*/ {
+/*N*/ aToSize.Width() = nWidth;
+/*N*/ }
+
+
+/*N*/ void SmPolyLineNode::AdaptToY(const OutputDevice &rDev, ULONG nHeight)
+/*N*/ {
+/*N*/ GetFont().FreezeBorderWidth();
+/*N*/ aToSize.Height() = nHeight;
+/*N*/ }
+
+
+/*N*/ void SmPolyLineNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ //! some routines being called extract some info from the OutputDevice's
+/*N*/ //! font (eg the space to be used for borders OR the font name(!!)).
+/*N*/ //! Thus the font should reflect the needs and has to be set!
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ long nBorderwidth = GetFont().GetBorderWidth();
+/*N*/
+/*N*/ //
+/*N*/ // Das Polygon mit den beiden Endpunkten bilden
+/*N*/ //
+/*N*/ DBG_ASSERT(aPoly.GetSize() == 2, "Sm : falsche Anzahl von Punkten");
+/*N*/ Point aPointA, aPointB;
+/*N*/ if (GetToken().eType == TWIDESLASH)
+/*N*/ {
+/*N*/ aPointA.X() = nBorderwidth;
+/*N*/ aPointA.Y() = aToSize.Height() - nBorderwidth;
+/*N*/ aPointB.X() = aToSize.Width() - nBorderwidth;
+/*N*/ aPointB.Y() = nBorderwidth;
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ DBG_ASSERT(GetToken().eType == TWIDEBACKSLASH, "Sm : unerwartetes Token");
+/*N*/ aPointA.X() =
+/*N*/ aPointA.Y() = nBorderwidth;
+/*N*/ aPointB.X() = aToSize.Width() - nBorderwidth;
+/*N*/ aPointB.Y() = aToSize.Height() - nBorderwidth;
+/*N*/ }
+/*N*/ aPoly.SetPoint(aPointA, 0);
+/*N*/ aPoly.SetPoint(aPointB, 1);
+/*N*/
+/*N*/ long nThick = GetFont().GetSize().Height()
+/*N*/ * rFormat.GetDistance(DIS_STROKEWIDTH) / 100L;
+/*N*/ nWidth = nThick + 2 * nBorderwidth;
+/*N*/
+/*N*/ SmRect::operator = (SmRect(aToSize.Width(), aToSize.Height()));
+/*N*/ }
+
+
+void SmPolyLineNode::Draw(OutputDevice &rDev, const Point &rPosition) const
+{
+ if (IsPhantom())
+ return;
+
+ long nBorderwidth = GetFont().GetBorderWidth();
+
+ LineInfo aInfo;
+ aInfo.SetWidth(nWidth - 2 * nBorderwidth);
+
+ Point aOffset (Point() - aPoly.GetBoundRect().TopLeft()
+ + Point(nBorderwidth, nBorderwidth)),
+ aPos (rPosition + aOffset);
+ ((Polygon &) aPoly).Move(aPos.X(), aPos.Y());
+
+ SmTmpDevice aTmpDev ((OutputDevice &) rDev, FALSE);
+ aTmpDev.SetLineColor( GetFont().GetColor() );
+
+ rDev.DrawPolyLine(aPoly, aInfo);
+
+ #ifdef SM_RECT_DEBUG
+ if (!IsDebug())
+ return;
+
+ int nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
+ SmRect::Draw(rDev, rPosition, nRFlags);
+ #endif
+}
+
+
+/**************************************************************************/
+
+/*N*/ void SmRootSymbolNode::AdaptToX(const OutputDevice &rDev, ULONG nWidth)
+/*N*/ {
+/*N*/ nBodyWidth = nWidth;
+/*N*/ }
+
+
+/*N*/ void SmRootSymbolNode::AdaptToY(const OutputDevice &rDev, ULONG nHeight)
+/*N*/ {
+/*N*/ // etwas extra Laenge damit der horizontale Balken spaeter ueber dem
+/*N*/ // Argument positioniert ist
+/*N*/ SmMathSymbolNode::AdaptToY(rDev, nHeight + nHeight / 10L);
+/*N*/ }
+
+
+void SmRootSymbolNode::Draw(OutputDevice &rDev, const Point &rPosition) const
+{
+ if (IsPhantom())
+ return;
+
+ // draw root-sign itself
+ SmMathSymbolNode::Draw(rDev, rPosition);
+
+ static String aBarStr( (sal_Unicode) MS_BAR );
+ SmTmpDevice aTmpDev( (OutputDevice &) rDev, TRUE );
+ aTmpDev.SetFillColor(GetFont().GetColor());
+ rDev.SetLineColor();
+ aTmpDev.SetFont( GetFont() );
+
+ // since the width is always unscaled it corresponds ot the _original_
+ // _unscaled_ font height to be used, we use that to calculate the
+ // bar height. Thus it is independent of the arguments height.
+ // ( see display of sqrt QQQ versus sqrt stack{Q#Q#Q#Q} )
+ long nBarHeight = GetWidth() * 7L / 100L;
+ long nBarWidth = nBodyWidth + GetBorderWidth();
+ Point aBarOffset( GetWidth(), +GetBorderWidth() );
+ Point aBarPos( rPosition + aBarOffset );
+
+ Rectangle aBar(aBarPos, Size( nBarWidth, nBarHeight) );
+ //! avoid GROWING AND SHRINKING of drawn rectangle when constantly
+ //! increasing zoomfactor.
+ // This is done by shifting it's output-position to a point that
+ // corresponds exactly to a pixel on the output device.
+ Point aDrawPos( rDev.PixelToLogic(rDev.LogicToPixel(aBar.TopLeft())) );
+ //aDrawPos.X() = aBar.Left(); //! don't change X position
+ aBar.SetPos( aDrawPos );
+
+ rDev.DrawRect( aBar );
+
+#ifdef SM_RECT_DEBUG
+ if (!IsDebug())
+ return;
+
+ int nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
+ SmRect::Draw(rDev, rPosition, nRFlags);
+#endif
+}
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmRectangleNode::AdaptToX(const OutputDevice &rDev, ULONG nWidth)
+/*N*/ {
+/*N*/ aToSize.Width() = nWidth;
+/*N*/ }
+
+
+/*N*/ void SmRectangleNode::AdaptToY(const OutputDevice &rDev, ULONG nHeight)
+/*N*/ {
+/*N*/ GetFont().FreezeBorderWidth();
+/*N*/ aToSize.Height() = nHeight;
+/*N*/ }
+
+
+/*N*/ void SmRectangleNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ long nFontHeight = GetFont().GetSize().Height();
+/*N*/ long nWidth = aToSize.Width(),
+/*N*/ nHeight = aToSize.Height();
+/*N*/ if (nHeight == 0)
+/*?*/ nHeight = nFontHeight / 30;
+/*N*/ if (nWidth == 0)
+/*?*/ nWidth = nFontHeight / 3;
+/*N*/
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ // add some borderspace
+/*N*/ ULONG nBorderWidth = GetFont().GetBorderWidth();
+/*N*/ //nWidth += nBorderWidth;
+/*N*/ nHeight += 2 * nBorderWidth;
+/*N*/
+/*N*/ //! use this method in order to have 'SmRect::HasAlignInfo() == TRUE'
+/*N*/ //! and thus having the attribut-fences updated in 'SmRect::ExtendBy'
+/*N*/ SmRect::operator = (SmRect(nWidth, nHeight));
+/*N*/ }
+
+
+void SmRectangleNode::Draw(OutputDevice &rDev, const Point &rPosition) const
+{
+ if (IsPhantom())
+ return;
+
+ SmTmpDevice aTmpDev ((OutputDevice &) rDev, FALSE);
+ aTmpDev.SetFillColor(GetFont().GetColor());
+ rDev.SetLineColor();
+ aTmpDev.SetFont(GetFont());
+
+ ULONG nBorderWidth = GetFont().GetBorderWidth();
+
+ // get rectangle and remove borderspace
+ Rectangle aTmp (AsRectangle() + rPosition - GetTopLeft());
+ aTmp.Left() += nBorderWidth;
+ aTmp.Right() -= nBorderWidth;
+ aTmp.Top() += nBorderWidth;
+ aTmp.Bottom() -= nBorderWidth;
+
+ DBG_ASSERT(aTmp.GetHeight() > 0 && aTmp.GetWidth() > 0,
+ "Sm: leeres Rechteck");
+
+ //! avoid GROWING AND SHRINKING of drawn rectangle when constantly
+ //! increasing zoomfactor.
+ // This is done by shifting it's output-position to a point that
+ // corresponds exactly to a pixel on the output device.
+ Point aPos (rDev.PixelToLogic(rDev.LogicToPixel(aTmp.TopLeft())));
+ aTmp.SetPos(aPos);
+
+ rDev.DrawRect(aTmp);
+
+ #ifdef SM_RECT_DEBUG
+ if (!IsDebug())
+ return;
+
+ int nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
+ SmRect::Draw(rDev, rPosition, nRFlags);
+ #endif
+}
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmTextNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
+/*N*/ {
+/*N*/ SmNode::Prepare(rFormat, rDocShell);
+/*N*/
+/*N*/ // default setting for horizontal alignment of nodes with TTEXT
+/*N*/ // content is as alignl (cannot be done in Arrange since it would
+/*N*/ // override the settings made by an SmAlignNode before)
+/*N*/ if (TTEXT == GetToken().eType)
+/*N*/ SetRectHorAlign( RHA_LEFT );
+/*N*/
+/*N*/ aText = GetToken().aText;
+/*N*/ GetFont() = rFormat.GetFont(GetFontDesc());
+/*N*/
+/*N*/ if (GetFont().GetItalic() == ITALIC_NORMAL)
+/*N*/ Attributes() |= ATTR_ITALIC;
+/*N*/ if (GetFont().GetWeight() == WEIGHT_BOLD)
+/*?*/ Attributes() |= ATTR_BOLD;
+/*N*/
+/*N*/ };
+
+
+/*N*/ void SmTextNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ PrepareAttributes();
+/*N*/
+/*N*/ USHORT nSizeDesc = GetFontDesc() == FNT_FUNCTION ?
+/*N*/ SIZ_FUNCTION : SIZ_TEXT;
+/*N*/ GetFont() *= Fraction (rFormat.GetRelSize(nSizeDesc), 100);
+/*N*/
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ SmRect::operator = (SmRect(aTmpDev, &rFormat, aText, GetFont().GetBorderWidth()));
+/*N*/ }
+
+
+/*N*/ void SmTextNode::Draw(OutputDevice &rDev, const Point& rPosition) const
+/*N*/ {
+/*N*/ if (IsPhantom() || aText.Len() == 0 || aText.GetChar(0) == xub_Unicode('\0'))
+/*N*/ return;
+/*N*/
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, FALSE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ Point aPos (rPosition);
+/*N*/ aPos.Y() += GetBaselineOffset();
+/*N*/ // auf Pixelkoordinaten runden
+/*N*/ aPos = rDev.PixelToLogic( rDev.LogicToPixel(aPos) );
+/*N*/
+/*N*/ rDev.DrawStretchText(aPos, GetWidth(), aText);
+/*N*/
+/*N*/ #ifdef SM_RECT_DEBUG
+/*N*/ if (!IsDebug())
+/*N*/ return;
+/*N*/
+/*N*/ int nRFlags = SM_RECT_CORE | SM_RECT_ITALIC | SM_RECT_LINES | SM_RECT_MID;
+/*N*/ SmRect::Draw(rDev, rPosition, nRFlags);
+/*N*/ #endif
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+
+/*N*/ void SmMatrixNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ Point aPosition,
+/*N*/ aOffset;
+/*N*/ SmNode *pNode;
+/*N*/ int i, j;
+/*N*/
+/*N*/ // initialize array that is to hold the maximum widhts of all
+/*N*/ // elements (subnodes) in that column.
+/*N*/ long *pColWidth = new long[nNumCols];
+/*N*/ for (j = 0; j < nNumCols; j++)
+/*N*/ pColWidth[j] = 0;
+/*N*/
+/*N*/ // arrange subnodes and calculate the aboves arrays contents
+/*N*/ for (i = GetNumSubNodes() - 1; i >= 0; i--)
+/*N*/ if (pNode = GetSubNode(i))
+/*N*/ { pNode->Arrange(rDev, rFormat);
+/*N*/
+/*N*/ int nCol = i % nNumCols;
+/*N*/ pColWidth[nCol]
+/*N*/ = Max(pColWidth[nCol], pNode->GetItalicWidth());
+/*N*/ }
+/*N*/
+/*N*/ // norm distance from which the following two are calcutated
+/*N*/ const int nNormDist = 3 * GetFont().GetSize().Height();
+/*N*/
+/*N*/ // define horizontal and vertical minimal distances that seperate
+/*N*/ // the elements
+/*N*/ long nHorDist = nNormDist * rFormat.GetDistance(DIS_MATRIXCOL) / 100L,
+/*N*/ nVerDist = nNormDist * rFormat.GetDistance(DIS_MATRIXROW) / 100L;
+/*N*/
+/*N*/ // build array that holds the leftmost position for each column
+/*N*/ long *pColLeft = new long[nNumCols];
+/*N*/ long nX = 0;
+/*N*/ for (j = 0; j < nNumCols; j++)
+/*N*/ { pColLeft[j] = nX;
+/*N*/ nX += pColWidth[j] + nHorDist;
+/*N*/ }
+/*N*/
+/*N*/ Point aPos, aDelta;
+/*N*/ SmRect aLineRect;
+/*N*/ SmRect::operator = (SmRect());
+/*N*/ for (i = 0; i < nNumRows; i++)
+/*N*/ { aLineRect = SmRect();
+/*N*/ for (j = 0; j < nNumCols; j++)
+/*N*/ { SmNode *pNode = GetSubNode(i * nNumCols + j);
+/*N*/ DBG_ASSERT(pNode, "Sm: NULL pointer");
+/*N*/
+/*N*/ const SmRect &rNodeRect = pNode->GetRect();
+/*N*/
+/*N*/ // align all baselines in that row if possible
+/*N*/ aPos = rNodeRect.AlignTo(aLineRect, RP_RIGHT, RHA_CENTER, RVA_BASELINE);
+/*N*/ aPos.X() += nHorDist;
+/*N*/
+/*N*/ // get horizontal alignment
+/*N*/ const SmNode *pCoNode = pNode->GetLeftMost();
+/*N*/ SmTokenType eType = pCoNode->GetToken().eType;
+/*N*/ RectHorAlign eHorAlign = pCoNode->GetRectHorAlign();
+/*N*/
+/*N*/ // caculate horizontal position of element depending on column
+/*N*/ // and horizontal alignment
+/*N*/ switch (eHorAlign)
+/*N*/ { case RHA_LEFT:
+/*N*/ aPos.X() = rNodeRect.GetLeft() + pColLeft[j];
+/*N*/ break;
+/*N*/ case RHA_CENTER:
+/*N*/ aPos.X() = rNodeRect.GetLeft() + pColLeft[j]
+/*N*/ + pColWidth[j] / 2
+/*N*/ - rNodeRect.GetItalicCenterX();
+/*N*/ break;
+/*N*/ case RHA_RIGHT:
+/*?*/ aPos.X() = rNodeRect.GetLeft() + pColLeft[j]
+/*?*/ + pColWidth[j] - rNodeRect.GetItalicWidth();
+/*N*/ break;
+/*N*/ }
+/*N*/
+/*N*/ pNode->MoveTo(aPos);
+/*N*/ aLineRect.ExtendBy(rNodeRect, RCP_XOR);
+/*N*/ }
+/*N*/
+/*N*/ aPos = aLineRect.AlignTo(*this, RP_BOTTOM, RHA_CENTER, RVA_BASELINE);
+/*N*/ aPos.Y() += nVerDist;
+/*N*/
+/*N*/ // move 'aLineRect' and rectangles in that line to final position
+/*N*/ aDelta.X() = 0; // since horizontal alignment is already done
+/*N*/ aDelta.Y() = aPos.Y() - aLineRect.GetTop();
+/*N*/ aLineRect.Move(aDelta);
+/*N*/ for (j = 0; j < nNumCols; j++)
+/*N*/ if (pNode = GetSubNode(i * nNumCols + j))
+/*N*/ pNode->Move(aDelta);
+/*N*/
+/*N*/ ExtendBy(aLineRect, RCP_NONE);
+/*N*/ }
+/*N*/
+/*N*/ delete [] pColLeft;
+/*N*/ delete [] pColWidth;
+/*N*/ }
+
+
+/*N*/ void SmMatrixNode::SetRowCol(USHORT nMatrixRows, USHORT nMatrixCols)
+/*N*/ {
+/*N*/ nNumRows = nMatrixRows;
+/*N*/ nNumCols = nMatrixCols;
+/*N*/ }
+
+
+/*N*/ SmNode * SmMatrixNode::GetLeftMost()
+/*N*/ {
+/*N*/ return this;
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ SmMathSymbolNode::SmMathSymbolNode(const SmToken &rNodeToken)
+/*N*/ : SmSpecialNode(NMATH, rNodeToken, FNT_MATH)
+/*N*/ {
+/*N*/ xub_Unicode cChar = GetToken().cMathChar;
+/*N*/ if ((xub_Unicode) '\0' != cChar)
+/*N*/ SetText( cChar );
+/*N*/ }
+
+/*?*/ void SmMathSymbolNode::AdaptToX(const OutputDevice &rDev, ULONG nWidth)
+/*?*/ {
+/*?*/ // Since there is no function to do this, we try to approximate it:
+/*?*/ Size aFntSize (GetFont().GetSize());
+/*?*/
+/*?*/ //! however the result is a bit better with 'nWidth' as initial font width
+/*?*/ aFntSize.Width() = nWidth;
+/*?*/ GetFont().SetSize(aFntSize);
+/*?*/
+/*?*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*?*/ aTmpDev.SetFont(GetFont());
+/*?*/
+/*?*/ // get denominator of error factor for width
+/*?*/ long nBorderWidth = GetFont().GetBorderWidth();
+/*?*/ long nDenom = SmRect(aTmpDev, NULL, GetText(), nBorderWidth).GetItalicWidth();
+/*?*/
+/*?*/ // scale fontwidth with this error factor
+/*?*/ aFntSize.Width() *= nWidth;
+/*?*/ aFntSize.Width() /= nDenom ? nDenom : 1;
+/*?*/
+/*?*/ GetFont().SetSize(aFntSize);
+/*?*/ }
+
+/*N*/ void SmMathSymbolNode::AdaptToY(const OutputDevice &rDev, ULONG nHeight)
+/*N*/ {
+/*N*/ GetFont().FreezeBorderWidth();
+/*N*/ Size aFntSize (GetFont().GetSize());
+/*N*/
+/*N*/ // da wir nur die Hoehe skalieren wollen muesen wir hier ggf die Fontweite
+/*N*/ // ermitteln um diese beizubehalten.
+/*N*/ if (aFntSize.Width() == 0)
+/*N*/ {
+/*N*/ OutputDevice &rDevNC = (OutputDevice &) rDev;
+/*N*/ rDevNC.Push(PUSH_FONT | PUSH_MAPMODE);
+/*N*/ rDevNC.SetFont(GetFont());
+/*N*/ aFntSize.Width() = rDev.GetFontMetric().GetSize().Width();
+/*N*/ rDevNC.Pop();
+/*N*/ }
+/*N*/ DBG_ASSERT(aFntSize.Width() != 0, "Sm: ");
+/*N*/
+/*N*/ //! however the result is a bit better with 'nHeight' as initial
+/*N*/ //! font height
+/*N*/ aFntSize.Height() = nHeight;
+/*N*/ GetFont().SetSize(aFntSize);
+/*N*/
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ // get denominator of error factor for height
+/*N*/ long nBorderWidth = GetFont().GetBorderWidth();
+/*N*/ long nDenom = SmRect(aTmpDev, NULL, GetText(), nBorderWidth).GetHeight();
+/*N*/
+/*N*/ // scale fontwidth with this error factor
+/*N*/ aFntSize.Height() *= nHeight;
+/*N*/ aFntSize.Height() /= nDenom ? nDenom : 1;
+/*N*/
+/*N*/ GetFont().SetSize(aFntSize);
+/*N*/ }
+
+
+/*N*/ void SmMathSymbolNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
+/*N*/ {
+/*N*/ SmNode::Prepare(rFormat, rDocShell);
+/*N*/
+/*N*/ DBG_ASSERT(GetFont().GetCharSet() == RTL_TEXTENCODING_SYMBOL ||
+/*N*/ GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE,
+/*N*/ "incorrect charset for character from StarMath/StarSymbol font");
+/*N*/
+/*N*/ Flags() |= FLG_FONT | FLG_ITALIC;
+/*N*/ };
+
+
+/*N*/ void SmMathSymbolNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ const XubString &rText = GetText();
+/*N*/
+/*N*/ if (rText.Len() == 0 || rText.GetChar(0) == xub_Unicode('\0'))
+/*N*/ { SmRect::operator = (SmRect());
+/*N*/ return;
+/*N*/ }
+/*N*/
+/*N*/ PrepareAttributes();
+/*N*/
+/*N*/ GetFont() *= Fraction (rFormat.GetRelSize(SIZ_TEXT), 100);
+/*N*/
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth()));
+/*N*/ }
+
+
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmSpecialNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
+/*N*/ {
+/*N*/ SmNode::Prepare(rFormat, rDocShell);
+/*N*/
+/*N*/ const SmSym *pSym;
+/*N*/ SmModule *pp = SM_MOD1();
+/*N*/
+/*N*/ Size aOldSize = GetFont().GetSize();
+/*N*/ if (pSym = rDocShell.GetSymSetManager().GetSymbolByName(GetToken().aText))
+/*N*/ {
+/*N*/ SetText( pSym->GetCharacter() );
+/*N*/ GetFont() = pSym->GetFace();
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ SetText( GetToken().aText );
+/*N*/ GetFont() = rFormat.GetFont(FNT_VARIABLE);
+/*N*/ }
+/*N*/ GetFont().SetSize(aOldSize);
+/*N*/
+/*N*/ //! eigentlich sollten nur WEIGHT_NORMAL und WEIGHT_BOLD vorkommen...
+/*N*/ //! In der sms-Datei gibt es jedoch zB auch 'WEIGHT_ULTRALIGHT'
+/*N*/ //! daher vergleichen wir hier mit > statt mit != .
+/*N*/ //! (Langfristig sollte die Notwendigkeit fuer 'PrepareAttribut', und damit
+/*N*/ //! fuer dieses hier, mal entfallen.)
+/*N*/ //
+/*N*/ //! see also SmFontStyles::GetStyleName
+/*N*/ if (GetFont().GetWeight() > WEIGHT_NORMAL)
+/*?*/ SetAttribut(ATTR_BOLD);
+/*N*/ if (GetFont().GetItalic() != ITALIC_NONE)
+/*N*/ SetAttribut(ATTR_ITALIC);
+/*N*/
+/*N*/ Flags() |= FLG_FONT;
+/*N*/ };
+
+
+/*N*/ void SmSpecialNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ PrepareAttributes();
+/*N*/
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth()));
+/*N*/ }
+
+
+/*N*/ void SmSpecialNode::Draw(OutputDevice &rDev, const Point& rPosition) const
+/*N*/ {
+/*N*/ //! since this chars might come from any font, that we may not have
+/*N*/ //! set to ALIGN_BASELINE yet, we do it now.
+/*N*/ ((SmSpecialNode *)this)->GetFont().SetAlign(ALIGN_BASELINE);
+/*N*/
+/*N*/ SmTextNode::Draw(rDev, rPosition);
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+void SmGlyphSpecialNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+{
+ PrepareAttributes();
+
+ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+ aTmpDev.SetFont(GetFont());
+
+ SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(),
+ GetFont().GetBorderWidth()).AsGlyphRect());
+}
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmPlaceNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
+/*N*/ {
+/*N*/ SmNode::Prepare(rFormat, rDocShell);
+/*N*/
+/*N*/ GetFont().SetColor(COL_GRAY);
+/*N*/ Flags() |= FLG_COLOR | FLG_FONT | FLG_ITALIC;
+/*N*/ };
+
+
+/*N*/ void SmPlaceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ PrepareAttributes();
+/*N*/
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth()));
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmErrorNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
+/*N*/ {
+/*N*/ SmNode::Prepare(rFormat, rDocShell);
+/*N*/
+/*N*/ GetFont().SetColor(COL_RED);
+/*N*/ Flags() |= FLG_VISIBLE | FLG_BOLD | FLG_ITALIC
+/*N*/ | FLG_COLOR | FLG_FONT | FLG_SIZE;
+/*N*/ }
+
+
+/*N*/ void SmErrorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ PrepareAttributes();
+/*N*/
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ const XubString &rText = GetText();
+/*N*/ DBG_ASSERT(rText.Len() == 1 && rText.GetChar(0) == (xub_Unicode) MS_ERROR,
+/*N*/ "Sm : Text ist kein ERROR Symbol");
+/*N*/ SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth()));
+/*N*/ }
+
+
+/**************************************************************************/
+
+
+/*N*/ void SmBlankNode::IncreaseBy(const SmToken &rToken)
+/*N*/ {
+/*N*/ switch(rToken.eType)
+/*N*/ {
+/*N*/ case TBLANK: nNum += 4; break;
+/*?*/ case TSBLANK: nNum += 1; break;
+/*N*/ }
+/*N*/ }
+
+
+/*N*/ void SmBlankNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
+/*N*/ {
+/*N*/ SmNode::Prepare(rFormat, rDocShell);
+/*N*/
+/*N*/ //! hier mu?sollte es lediglich nicht der StarMath Font sein,
+/*N*/ //! damit fuer das in Arrange verwendete Zeichen ein "normales"
+/*N*/ //! (ungecliptes) Rechteck erzeugt wird.
+/*N*/ GetFont() = rFormat.GetFont(FNT_VARIABLE);
+/*N*/
+/*N*/ Flags() |= FLG_FONT | FLG_BOLD | FLG_ITALIC;
+/*N*/ }
+
+
+/*N*/ void SmBlankNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
+/*N*/ {
+/*N*/ SmTmpDevice aTmpDev ((OutputDevice &) rDev, TRUE);
+/*N*/ aTmpDev.SetFont(GetFont());
+/*N*/
+/*N*/ // Abstand von der Fonthoehe abhaengig machen
+/*N*/ // (damit er beim skalieren (zB size *2 {a ~ b}) mitwaechst)
+/*N*/ long nDist = GetFont().GetSize().Height() / 10L,
+/*N*/ nSpace = nNum * nDist;
+/*N*/
+/*N*/ // ein SmRect mit Baseline und allem drum und dran besorgen
+/*N*/ SmRect::operator = (SmRect(aTmpDev, &rFormat, XubString(xub_Unicode(' ')),
+/*N*/ GetFont().GetBorderWidth()));
+/*N*/
+/*N*/ // und dieses auf die gewuenschte Breite bringen
+/*N*/ SetItalicSpaces(0, 0);
+/*N*/ SetWidth(nSpace);
+/*N*/ }
+
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */