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