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