LibreOffice Module starmath (master) 1
node.cxx
Go to the documentation of this file.
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 <symbol.hxx>
22#include <smmod.hxx>
23#include "tmpdevice.hxx"
24#include <utility>
25#include <visitors.hxx>
27#include <vcl/metric.hxx>
28#include <o3tl/safeint.hxx>
29#include <osl/diagnose.h>
31
32namespace {
33
34template<typename F>
35void ForEachNonNull(SmNode *pNode, F && f)
36{
37 size_t nSize = pNode->GetNumSubNodes();
38 for (size_t i = 0; i < nSize; ++i)
39 {
40 SmNode *pSubNode = pNode->GetSubNode(i);
41 if (pSubNode != nullptr)
42 f(pSubNode);
43 }
44}
45
46}
47
48SmNode::SmNode(SmNodeType eNodeType, SmToken aNodeToken)
49 : maNodeToken(std::move( aNodeToken ))
50 , meType( eNodeType )
51 , meScaleMode( SmScaleMode::None )
52 , meRectHorAlign( RectHorAlign::Left )
54 , mnAttributes( FontAttribute::None )
55 , mbIsPhantom( false )
56 , mbIsSelected( false )
57 , mnAccIndex( -1 )
58 , mpParentNode( nullptr )
59{
60}
61
63{
64}
65
67 // returns leftmost node of current subtree.
70{
71 const SmNode *pNode = GetNumSubNodes() > 0 ?
72 GetSubNode(0) : nullptr;
73
74 return pNode ? pNode->GetLeftMost() : this;
75}
76
77
78void SmNode::SetPhantom(bool bIsPhantomP)
79{
81 mbIsPhantom = bIsPhantomP;
82
83 bool b = mbIsPhantom;
84 ForEachNonNull(this, [b](SmNode *pNode){pNode->SetPhantom(b);});
85}
86
87
88void SmNode::SetColor(const Color& rColor)
89{
90 if (! (Flags() & FontChangeMask::Color))
91 GetFont().SetColor(rColor);
92
93 ForEachNonNull(this, [&rColor](SmNode *pNode){pNode->SetColor(rColor);});
94}
95
96
98{
99 if (
100 (nAttrib == FontAttribute::Bold && !(Flags() & FontChangeMask::Bold)) ||
102 )
103 {
104 mnAttributes |= nAttrib;
105 }
106
107 ForEachNonNull(this, [nAttrib](SmNode *pNode){pNode->SetAttribute(nAttrib);});
108}
109
110
112{
113 if (
114 (nAttrib == FontAttribute::Bold && !(Flags() & FontChangeMask::Bold)) ||
116 )
117 {
118 mnAttributes &= ~nAttrib;
119 }
120
121 ForEachNonNull(this, [nAttrib](SmNode *pNode){pNode->ClearAttribute(nAttrib);});
122}
123
124
125void SmNode::SetFont(const SmFace &rFace)
126{
127 if (!(Flags() & FontChangeMask::Face))
128 GetFont() = rFace;
129 ForEachNonNull(this, [&rFace](SmNode *pNode){pNode->SetFont(rFace);});
130}
131
132
135{
136 Size aFntSize;
137
138 if (!(Flags() & FontChangeMask::Size))
139 {
141 tools::Long nHeight = static_cast<tools::Long>(aVal);
142
143 aFntSize = GetFont().GetFontSize();
144 aFntSize.setWidth( 0 );
145 switch(nType)
146 {
148 aFntSize.setHeight( nHeight );
149 break;
150
152 aFntSize.AdjustHeight(nHeight );
153 break;
154
156 aFntSize.AdjustHeight( -nHeight );
157 break;
158
160 aFntSize.setHeight( static_cast<tools::Long>(Fraction(aFntSize.Height()) * rSize) );
161 break;
162
164 if (rSize != Fraction(0))
165 aFntSize.setHeight( static_cast<tools::Long>(Fraction(aFntSize.Height()) / rSize) );
166 break;
167 default:
168 break;
169 }
170
171 // check the requested size against maximum value
172 const int nMaxVal = o3tl::convert(128, o3tl::Length::pt, SmO3tlLengthUnit());
173 if (aFntSize.Height() > nMaxVal)
174 aFntSize.setHeight( nMaxVal );
175
176 GetFont().SetSize(aFntSize);
177 }
178
179 ForEachNonNull(this, [&rSize, &nType](SmNode *pNode){pNode->SetFontSize(rSize, nType);});
180}
181
182
183void SmNode::SetSize(const Fraction &rSize)
184{
185 GetFont() *= rSize;
186
187 ForEachNonNull(this, [&rSize](SmNode *pNode){pNode->SetSize(rSize);});
188}
189
190
191void SmNode::SetRectHorAlign(RectHorAlign eHorAlign, bool bApplyToSubTree )
192{
193 meRectHorAlign = eHorAlign;
194
195 if (bApplyToSubTree)
196 ForEachNonNull(this, [eHorAlign](SmNode *pNode){pNode->SetRectHorAlign(eHorAlign);});
197}
198
199
201{
204}
205
206
207void SmNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
208{
209 if (nDepth > 1024)
210 throw std::range_error("parser depth limit");
211
212 mbIsPhantom = false;
215
216 switch (rFormat.GetHorAlign())
220 }
221
222 GetFont() = rFormat.GetFont(FNT_MATH);
223 OSL_ENSURE( GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE,
224 "unexpected CharSet" );
227
228 ForEachNonNull(this, [&rFormat, &rDocShell, nDepth](SmNode *pNode){pNode->Prepare(rFormat, rDocShell, nDepth + 1);});
229}
230
231void SmNode::Move(const Point& rVector)
232{
233 if (rVector.X() == 0 && rVector.Y() == 0)
234 return;
235
236 SmRect::Move(rVector);
237
238 ForEachNonNull(this, [&rVector](SmNode *pNode){pNode->Move(rVector);});
239}
240
241void SmNode::AdaptToX(OutputDevice &/*rDev*/, sal_uLong /*nWidth*/)
242{
243}
244
245
246void SmNode::AdaptToY(OutputDevice &/*rDev*/, sal_uLong /*nHeight*/)
247{
248}
249
250
251const SmNode * SmNode::FindTokenAt(sal_uInt16 nRow, sal_uInt16 nCol) const
252 // returns (first) ** visible ** (sub)node with the tokens text at
253 // position 'nRow', 'nCol'.
255{
256 if ( IsVisible()
257 && nRow == GetSelection().nStartPara
258 && nCol >= GetSelection().nStartPos && nCol <= GetSelection().nEndPos )
259 return this;
260 else
261 {
262 size_t nNumSubNodes = GetNumSubNodes();
263 for (size_t i = 0; i < nNumSubNodes; ++i)
264 {
265 const SmNode *pNode = GetSubNode(i);
266
267 if (!pNode)
268 continue;
269
270 const SmNode *pResult = pNode->FindTokenAt(nRow, nCol);
271 if (pResult)
272 return pResult;
273 }
274 }
275
276 return nullptr;
277}
278
279
280const SmNode * SmNode::FindRectClosestTo(const Point &rPoint) const
281{
282 tools::Long nDist = LONG_MAX;
283 const SmNode *pResult = nullptr;
284
285 if (IsVisible())
286 pResult = this;
287 else
288 {
289 size_t nNumSubNodes = GetNumSubNodes();
290 for (size_t i = 0; i < nNumSubNodes; ++i)
291 {
292 const SmNode *pNode = GetSubNode(i);
293
294 if (!pNode)
295 continue;
296
297 const SmNode *pFound = pNode->FindRectClosestTo(rPoint);
298 if (pFound)
299 {
300 tools::Long nTmp = pFound->OrientedDist(rPoint);
301 if (nTmp < nDist)
302 {
303 nDist = nTmp;
304 pResult = pFound;
305
306 // quit immediately if 'rPoint' is inside the *should not
307 // overlap with other rectangles* part.
308 // This (partly) serves for getting the attributes in eg
309 // "bar overstrike a".
310 // ('nDist < 0' is used as *quick shot* to avoid evaluation of
311 // the following expression, where the result is already determined)
312 if (nDist < 0 && pFound->IsInsideRect(rPoint))
313 break;
314 }
315 }
316 }
317 }
318
319 return pResult;
320}
321
322const SmNode * SmNode::FindNodeWithAccessibleIndex(sal_Int32 nAccIdx) const
323{
324 const SmNode *pResult = nullptr;
325
326 sal_Int32 nIdx = GetAccessibleIndex();
327 OUStringBuffer aTxt;
328 if (nIdx >= 0)
329 GetAccessibleText( aTxt ); // get text if used in following 'if' statement
330
331 if (nIdx >= 0
332 && nIdx <= nAccIdx && nAccIdx < nIdx + aTxt.getLength())
333 pResult = this;
334 else
335 {
336 size_t nNumSubNodes = GetNumSubNodes();
337 for (size_t i = 0; i < nNumSubNodes; ++i)
338 {
339 const SmNode *pNode = GetSubNode(i);
340 if (!pNode)
341 continue;
342
343 pResult = pNode->FindNodeWithAccessibleIndex(nAccIdx);
344 if (pResult)
345 return pResult;
346 }
347 }
348
349 return pResult;
350}
351
352
354{
355 ForEachNonNull(this, std::default_delete<SmNode>());
356}
357
358
360{
361 maSubNodes.clear();
362}
363
364void SmStructureNode::SetSubNodes(std::unique_ptr<SmNode> pFirst, std::unique_ptr<SmNode> pSecond, std::unique_ptr<SmNode> pThird)
365{
366 size_t nSize = pThird ? 3 : (pSecond ? 2 : (pFirst ? 1 : 0));
367 maSubNodes.resize( nSize );
368 if (pFirst)
369 maSubNodes[0] = pFirst.release();
370 if (pSecond)
371 maSubNodes[1] = pSecond.release();
372 if (pThird)
373 maSubNodes[2] = pThird.release();
374
376}
377
378void SmStructureNode::SetSubNodes(SmNode* pFirst, SmNode* pSecond, SmNode* pThird)
379{
380 size_t nSize = pThird ? 3 : (pSecond ? 2 : (pFirst ? 1 : 0));
381 maSubNodes.resize( nSize );
382 if (pFirst)
383 maSubNodes[0] = pFirst;
384 if (pSecond)
385 maSubNodes[1] = pSecond;
386 if (pThird)
387 maSubNodes[2] = pThird;
388
390}
391
392void SmStructureNode::SetSubNodesBinMo(std::unique_ptr<SmNode> pFirst, std::unique_ptr<SmNode> pSecond, std::unique_ptr<SmNode> pThird)
393{
395 {
396 size_t nSize = pSecond ? 3 : (pThird ? 2 : (pFirst ? 1 : 0));
397 maSubNodes.resize( nSize );
398 if (pFirst)
399 maSubNodes[0] = pFirst.release();
400 if (pSecond)
401 maSubNodes[2] = pSecond.release();
402 if (pThird)
403 maSubNodes[1] = pThird.release();
404 }
405 else
406 {
407 size_t nSize = pThird ? 3 : (pSecond ? 2 : (pFirst ? 1 : 0));
408 maSubNodes.resize( nSize );
409 if (pFirst)
410 maSubNodes[0] = pFirst.release();
411 if (pSecond)
412 maSubNodes[1] = pSecond.release();
413 if (pThird)
414 maSubNodes[2] = pThird.release();
415 }
417}
418
420{
421 maSubNodes = std::move(rNodeArray);
423}
424
426{
427 return false;
428}
429
431{
432 return maSubNodes.size();
433}
434
436{
437 return maSubNodes[nIndex];
438}
439
441{
443 {
444 if (nIndex==1)
445 nIndex = 2;
446 else if (nIndex==2)
447 nIndex = 1;
448 }
449 return maSubNodes[nIndex];
450}
451
452void SmStructureNode::GetAccessibleText( OUStringBuffer &rText ) const
453{
454 ForEachNonNull(const_cast<SmStructureNode *>(this),
455 [&rText](SmNode *pNode)
456 {
457 if (pNode->IsVisible())
458 pNode->SetAccessibleIndex(rText.getLength());
459 pNode->GetAccessibleText( rText );
460 });
461}
462
464{
465 ForEachNonNull(this, [this](SmNode *pNode){pNode->SetParent(this);});
466}
467
469{
470 size_t nSize = GetNumSubNodes();
471 for (size_t i = 0; i < nSize; i++)
472 if (pSubNode == GetSubNode(i))
473 return i;
474 return -1;
475}
476
477void SmStructureNode::SetSubNode(size_t nIndex, SmNode* pNode)
478{
479 size_t size = maSubNodes.size();
480 if (size <= nIndex)
481 {
482 //Resize subnodes array
483 maSubNodes.resize(nIndex + 1);
484 //Set new slots to NULL except at nIndex
485 for (size_t i = size; i < nIndex; i++)
486 maSubNodes[i] = nullptr;
487 }
488 maSubNodes[nIndex] = pNode;
489 if (pNode)
490 pNode->SetParent(this);
491}
492
494{
495 return true;
496}
497
499{
500 return 0;
501}
502
504{
505 return nullptr;
506}
507
508void SmGraphicNode::GetAccessibleText( OUStringBuffer &rText ) const
509{
510 rText.append(GetToken().aText);
511}
512
513void SmTableNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
514 // arranges all subnodes in one column
515{
516 SmNode *pNode;
517 size_t nSize = GetNumSubNodes();
518
519 // make distance depend on font size
520 tools::Long nDist = +(rFormat.GetDistance(DIS_VERTICAL)
521 * GetFont().GetFontSize().Height()) / 100;
522
523 if (nSize < 1)
524 return;
525
526 // arrange subnodes and get maximum width of them
527 tools::Long nMaxWidth = 0,
528 nTmp;
529 for (size_t i = 0; i < nSize; ++i)
530 {
531 if (nullptr != (pNode = GetSubNode(i)))
532 { pNode->Arrange(rDev, rFormat);
533 if ((nTmp = pNode->GetItalicWidth()) > nMaxWidth)
534 nMaxWidth = nTmp;
535 }
536 }
537
538 Point aPos;
539 SmRect::operator = (SmRect(nMaxWidth, 1));
540 for (size_t i = 0; i < nSize; ++i)
541 {
542 if (nullptr != (pNode = GetSubNode(i)))
543 { const SmRect &rNodeRect = pNode->GetRect();
544 const SmNode *pCoNode = pNode->GetLeftMost();
545 RectHorAlign eHorAlign = pCoNode->GetRectHorAlign();
546
547 aPos = rNodeRect.AlignTo(*this, RectPos::Bottom,
548 eHorAlign, RectVerAlign::Baseline);
549 if (i)
550 aPos.AdjustY(nDist );
551 pNode->MoveTo(aPos);
552 ExtendBy(rNodeRect, nSize > 1 ? RectCopyMBL::None : RectCopyMBL::Arg);
553 }
554 }
555 // #i972#
556 if (HasBaseline())
558 else
559 {
560 SmTmpDevice aTmpDev (rDev, true);
561 aTmpDev.SetFont(GetFont());
562
563 SmRect aRect(aTmpDev, &rFormat, "a", GetFont().GetBorderWidth());
565 // move from middle position by constant - distance
566 // between middle and baseline for single letter
567 mnFormulaBaseline += aRect.GetBaseline() - aRect.GetAlignM();
568 }
569}
570
572{
573 return this;
574}
575
576
578{
579 return mnFormulaBaseline;
580}
581
582
583/**************************************************************************/
584
585
586void SmLineNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
587{
588 SmNode::Prepare(rFormat, rDocShell, nDepth);
589
590 // Here we use the 'FNT_VARIABLE' font since it's ascent and descent in general fit better
591 // to the rest of the formula compared to the 'FNT_MATH' font.
592 GetFont() = rFormat.GetFont(FNT_VARIABLE);
594}
595
596
597/**************************************************************************/
598
599
600void SmLineNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
601 // arranges all subnodes in one row with some extra space between
602{
603 SmNode *pNode;
604 size_t nSize = GetNumSubNodes();
605 for (size_t i = 0; i < nSize; ++i)
606 {
607 if (nullptr != (pNode = GetSubNode(i)))
608 pNode->Arrange(rDev, rFormat);
609 }
610
611 SmTmpDevice aTmpDev (rDev, true);
612 aTmpDev.SetFont(GetFont());
613
614 if (nSize < 1)
615 {
616 // provide an empty rectangle with alignment parameters for the "current"
617 // font (in order to make "a^1 {}_2^3 a_4" work correct, that is, have the
618 // same sub-/supscript positions.)
622 SmRect::operator = (SmRect(aTmpDev, &rFormat, "a",
624 // make sure that the rectangle occupies (almost) no space
625 SetWidth(1);
626 SetItalicSpaces(0, 0);
627 return;
628 }
629
630 // make distance depend on font size
631 tools::Long nDist = (rFormat.GetDistance(DIS_HORIZONTAL) * GetFont().GetFontSize().Height()) / 100;
632 if (!IsUseExtraSpaces())
633 nDist = 0;
634
635 Point aPos;
636 // copy the first node into LineNode and extend by the others
637 if (nullptr != (pNode = GetSubNode(0)))
638 SmRect::operator = (pNode->GetRect());
639
640 for (size_t i = 1; i < nSize; ++i)
641 {
642 if (nullptr != (pNode = GetSubNode(i)))
643 {
645
646 // add horizontal space to the left for each but the first sub node
647 aPos.AdjustX(nDist );
648
649 pNode->MoveTo(aPos);
650 ExtendBy( *pNode, RectCopyMBL::Xor );
651 }
652 }
653}
654
655
656/**************************************************************************/
657
658
660 // as 'SmLineNode::Arrange' but keeps alignment of leftmost subnode
661{
662 SmLineNode::Arrange(rDev, rFormat);
663
664 // copy alignment of leftmost subnode if any
665 const SmNode *pNode = GetLeftMost();
666 if (pNode)
667 SetRectHorAlign(pNode->GetRectHorAlign(), false);
668}
669
670
671/**************************************************************************/
672
673
674void SmUnHorNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
675{
676 bool bIsPostfix = GetToken().eType == TFACT;
677
678 SmNode *pNode0 = GetSubNode(0),
679 *pNode1 = GetSubNode(1);
680 SmNode *pOper = bIsPostfix ? pNode1 : pNode0,
681 *pBody = bIsPostfix ? pNode0 : pNode1;
682 assert(pOper);
683 assert(pBody);
684
685 pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100));
686 pOper->Arrange(rDev, rFormat);
687 pBody->Arrange(rDev, rFormat);
688
689 tools::Long nDist = (pOper->GetRect().GetWidth() * rFormat.GetDistance(DIS_HORIZONTAL)) / 100;
690
691 SmRect::operator = (*pNode0);
692
693 Point aPos = pNode1->AlignTo(*this, RectPos::Right, RectHorAlign::Center, RectVerAlign::Baseline);
694 aPos.AdjustX(nDist );
695 pNode1->MoveTo(aPos);
696 ExtendBy(*pNode1, RectCopyMBL::Xor);
697}
698
699
700/**************************************************************************/
701
702namespace {
703
704void lcl_GetHeightVerOffset(const SmRect &rRect,
705 tools::Long &rHeight, tools::Long &rVerOffset)
706 // calculate height and vertical offset of root sign suitable for 'rRect'
707{
708 rVerOffset = (rRect.GetBottom() - rRect.GetAlignB()) / 2;
709 rHeight = rRect.GetHeight() - rVerOffset;
710
711 OSL_ENSURE(rHeight >= 0, "Sm : Ooops...");
712 OSL_ENSURE(rVerOffset >= 0, "Sm : Ooops...");
713}
714
715
716Point lcl_GetExtraPos(const SmRect &rRootSymbol,
717 const SmRect &rExtra)
718{
719 const Size &rSymSize = rRootSymbol.GetSize();
720
721 Point aPos = rRootSymbol.GetTopLeft()
722 + Point((rSymSize.Width() * 70) / 100,
723 (rSymSize.Height() * 52) / 100);
724
725 // from this calculate topleft edge of 'rExtra'
726 aPos.AdjustX( -(rExtra.GetWidth() + rExtra.GetItalicRightSpace()) );
727 aPos.AdjustY( -(rExtra.GetHeight()) );
728 // if there's enough space move a bit less to the right
729 // examples: "nroot i a", "nroot j a"
730 // (it looks better if we don't use italic-spaces here)
731 tools::Long nX = rRootSymbol.GetLeft() + (rSymSize.Width() * 30) / 100;
732 if (aPos.X() > nX)
733 aPos.setX( nX );
734
735 return aPos;
736}
737
738}
739
740void SmRootNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
741{
746 SmNode *pExtra = GetSubNode(0),
747 *pRootSym = GetSubNode(1),
748 *pBody = GetSubNode(2);
749 assert(pRootSym);
750 assert(pBody);
751
752 pBody->Arrange(rDev, rFormat);
753
754 tools::Long nHeight,
755 nVerOffset;
756 lcl_GetHeightVerOffset(*pBody, nHeight, nVerOffset);
757 nHeight += rFormat.GetDistance(DIS_ROOT)
758 * GetFont().GetFontSize().Height() / 100;
759
760 if (nHeight < 0)
761 {
762 SAL_WARN("starmath", "negative height");
763 nHeight = 0;
764 }
765
766 // font specialist advised to change the width first
767 pRootSym->AdaptToY(rDev, nHeight);
768 pRootSym->AdaptToX(rDev, pBody->GetItalicWidth());
769
770 pRootSym->Arrange(rDev, rFormat);
771
772 Point aPos = pRootSym->AlignTo(*pBody, RectPos::Left, RectHorAlign::Center, RectVerAlign::Baseline);
774 aPos.setY( pRootSym->GetTop() + pBody->GetBottom() - pRootSym->GetBottom() );
775 aPos.AdjustY( -nVerOffset );
776 pRootSym->MoveTo(aPos);
777
778 if (pExtra)
779 { pExtra->SetSize(Fraction(rFormat.GetRelSize(SIZ_INDEX), 100));
780 pExtra->Arrange(rDev, rFormat);
781
782 aPos = lcl_GetExtraPos(*pRootSym, *pExtra);
783 pExtra->MoveTo(aPos);
784 }
785
786 SmRect::operator = (*pBody);
787 ExtendBy(*pRootSym, RectCopyMBL::This);
788 if (pExtra)
789 ExtendBy(*pExtra, RectCopyMBL::This, true);
790}
791
792/**************************************************************************/
793
794
795void SmBinHorNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
796{
797 SmNode *pLeft = LeftOperand(),
798 *pOper = Symbol(),
799 *pRight = RightOperand();
800 assert(pLeft);
801 assert(pOper);
802 assert(pRight);
803
804 pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100));
805
806 pLeft ->Arrange(rDev, rFormat);
807 pOper ->Arrange(rDev, rFormat);
808 pRight->Arrange(rDev, rFormat);
809
810 const SmRect &rOpRect = pOper->GetRect();
811
812 tools::Long nMul;
813 if (o3tl::checked_multiply<tools::Long>(rOpRect.GetWidth(), rFormat.GetDistance(DIS_HORIZONTAL), nMul))
814 {
815 SAL_WARN("starmath", "integer overflow");
816 return;
817 }
818
819 tools::Long nDist = nMul / 100;
820
821 SmRect::operator = (*pLeft);
822
823 Point aPos;
824 aPos = pOper->AlignTo(*this, RectPos::Right, RectHorAlign::Center, RectVerAlign::Baseline);
825 aPos.AdjustX(nDist );
826 pOper->MoveTo(aPos);
827 ExtendBy(*pOper, RectCopyMBL::Xor);
828
829 aPos = pRight->AlignTo(*this, RectPos::Right, RectHorAlign::Center, RectVerAlign::Baseline);
830 aPos.AdjustX(nDist );
831
832 pRight->MoveTo(aPos);
833 ExtendBy(*pRight, RectCopyMBL::Xor);
834}
835
836
837/**************************************************************************/
838
839
840void SmBinVerNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
841{
842 SmNode *pNum = GetSubNode(0),
843 *pLine = GetSubNode(1),
844 *pDenom = GetSubNode(2);
845 assert(pNum);
846 assert(pLine);
847 assert(pDenom);
848
849 bool bIsTextmode = rFormat.IsTextmode();
850 if (bIsTextmode)
851 {
852 Fraction aFraction(rFormat.GetRelSize(SIZ_INDEX), 100);
853 pNum ->SetSize(aFraction);
854 pLine ->SetSize(aFraction);
855 pDenom->SetSize(aFraction);
856 }
857
858 pNum ->Arrange(rDev, rFormat);
859 pDenom->Arrange(rDev, rFormat);
860
861 tools::Long nFontHeight = GetFont().GetFontSize().Height(),
862 nExtLen = nFontHeight * rFormat.GetDistance(DIS_FRACTION) / 100,
863 nThick = nFontHeight * rFormat.GetDistance(DIS_STROKEWIDTH) / 100,
864 nWidth = std::max(pNum->GetItalicWidth(), pDenom->GetItalicWidth()),
865 nNumDist = bIsTextmode ? 0 :
866 nFontHeight * rFormat.GetDistance(DIS_NUMERATOR) / 100,
867 nDenomDist = bIsTextmode ? 0 :
868 nFontHeight * rFormat.GetDistance(DIS_DENOMINATOR) / 100;
869
870 // font specialist advised to change the width first
871 pLine->AdaptToY(rDev, nThick);
872 pLine->AdaptToX(rDev, nWidth + 2 * nExtLen);
873 pLine->Arrange(rDev, rFormat);
874
875 // get horizontal alignment for numerator
876 const SmNode *pLM = pNum->GetLeftMost();
877 RectHorAlign eHorAlign = pLM->GetRectHorAlign();
878
879 // move numerator to its position
880 Point aPos = pNum->AlignTo(*pLine, RectPos::Top, eHorAlign, RectVerAlign::Baseline);
881 aPos.AdjustY( -nNumDist );
882 pNum->MoveTo(aPos);
883
884 // get horizontal alignment for denominator
885 pLM = pDenom->GetLeftMost();
886 eHorAlign = pLM->GetRectHorAlign();
887
888 // move denominator to its position
889 aPos = pDenom->AlignTo(*pLine, RectPos::Bottom, eHorAlign, RectVerAlign::Baseline);
890 aPos.AdjustY(nDenomDist );
891 pDenom->MoveTo(aPos);
892
893 SmRect::operator = (*pNum);
894 ExtendBy(*pDenom, RectCopyMBL::None).ExtendBy(*pLine, RectCopyMBL::None, pLine->GetCenterY());
895}
896
898{
899 return this;
900}
901
902
903namespace {
904
906double Det(const Point &rHeading1, const Point &rHeading2)
907{
908 return rHeading1.X() * rHeading2.Y() - rHeading1.Y() * rHeading2.X();
909}
910
911
914bool IsPointInLine(const Point &rPoint1,
915 const Point &rPoint2, const Point &rHeading2)
916{
917 assert(rHeading2 != Point());
918
919 bool bRes = false;
920 static const double eps = 5.0 * DBL_EPSILON;
921
922 double fLambda;
923 if (std::abs(rHeading2.X()) > std::abs(rHeading2.Y()))
924 {
925 fLambda = (rPoint1.X() - rPoint2.X()) / static_cast<double>(rHeading2.X());
926 bRes = fabs(rPoint1.Y() - (rPoint2.Y() + fLambda * rHeading2.Y())) < eps;
927 }
928 else
929 {
930 fLambda = (rPoint1.Y() - rPoint2.Y()) / static_cast<double>(rHeading2.Y());
931 bRes = fabs(rPoint1.X() - (rPoint2.X() + fLambda * rHeading2.X())) < eps;
932 }
933
934 return bRes;
935}
936
937
938sal_uInt16 GetLineIntersectionPoint(Point &rResult,
939 const Point& rPoint1, const Point &rHeading1,
940 const Point& rPoint2, const Point &rHeading2)
941{
942 assert(rHeading1 != Point());
943 assert(rHeading2 != Point());
944
945 sal_uInt16 nRes = 1;
946 static const double eps = 5.0 * DBL_EPSILON;
947
948 // are the direction vectors linearly dependent?
949 double fDet = Det(rHeading1, rHeading2);
950 if (fabs(fDet) < eps)
951 {
952 nRes = IsPointInLine(rPoint1, rPoint2, rHeading2) ? USHRT_MAX : 0;
953 rResult = nRes ? rPoint1 : Point();
954 }
955 else
956 {
957 // here we do not pay attention to the computational accuracy
958 // (that would be more complicated and is not really worth it in this case)
959 double fLambda = ( (rPoint1.Y() - rPoint2.Y()) * rHeading2.X()
960 - (rPoint1.X() - rPoint2.X()) * rHeading2.Y())
961 / fDet;
962 rResult = Point(rPoint1.X() + static_cast<tools::Long>(fLambda * rHeading1.X()),
963 rPoint1.Y() + static_cast<tools::Long>(fLambda * rHeading1.Y()));
964 }
965
966 return nRes;
967}
968
969}
970
971
975 const Point &rDiagPoint, double fAngleDeg) const
976
977{
978 double fAngleRad = basegfx::deg2rad(fAngleDeg);
979 tools::Long nRectLeft = GetItalicLeft(),
980 nRectRight = GetItalicRight(),
981 nRectTop = GetTop(),
982 nRectBottom = GetBottom();
983 Point aRightHdg (100, 0),
984 aDownHdg (0, 100),
985 aDiagHdg ( static_cast<tools::Long>(100.0 * cos(fAngleRad)),
986 static_cast<tools::Long>(-100.0 * sin(fAngleRad)) );
987
988 tools::Long nLeft, nRight, nTop, nBottom; // margins of the rectangle for the diagonal
989 Point aPoint;
990 if (IsAscending())
991 {
992 // determine top right corner
993 GetLineIntersectionPoint(aPoint,
994 Point(nRectLeft, nRectTop), aRightHdg,
995 rDiagPoint, aDiagHdg);
996 // is there a point of intersection with the top border?
997 if (aPoint.X() <= nRectRight)
998 {
999 nRight = aPoint.X();
1000 nTop = nRectTop;
1001 }
1002 else
1003 {
1004 // there has to be a point of intersection with the right border!
1005 GetLineIntersectionPoint(aPoint,
1006 Point(nRectRight, nRectTop), aDownHdg,
1007 rDiagPoint, aDiagHdg);
1008
1009 nRight = nRectRight;
1010 nTop = aPoint.Y();
1011 }
1012
1013 // determine bottom left corner
1014 GetLineIntersectionPoint(aPoint,
1015 Point(nRectLeft, nRectBottom), aRightHdg,
1016 rDiagPoint, aDiagHdg);
1017 // is there a point of intersection with the bottom border?
1018 if (aPoint.X() >= nRectLeft)
1019 {
1020 nLeft = aPoint.X();
1021 nBottom = nRectBottom;
1022 }
1023 else
1024 {
1025 // there has to be a point of intersection with the left border!
1026 GetLineIntersectionPoint(aPoint,
1027 Point(nRectLeft, nRectTop), aDownHdg,
1028 rDiagPoint, aDiagHdg);
1029
1030 nLeft = nRectLeft;
1031 nBottom = aPoint.Y();
1032 }
1033 }
1034 else
1035 {
1036 // determine top left corner
1037 GetLineIntersectionPoint(aPoint,
1038 Point(nRectLeft, nRectTop), aRightHdg,
1039 rDiagPoint, aDiagHdg);
1040 // is there a point of intersection with the top border?
1041 if (aPoint.X() >= nRectLeft)
1042 {
1043 nLeft = aPoint.X();
1044 nTop = nRectTop;
1045 }
1046 else
1047 {
1048 // there has to be a point of intersection with the left border!
1049 GetLineIntersectionPoint(aPoint,
1050 Point(nRectLeft, nRectTop), aDownHdg,
1051 rDiagPoint, aDiagHdg);
1052
1053 nLeft = nRectLeft;
1054 nTop = aPoint.Y();
1055 }
1056
1057 // determine bottom right corner
1058 GetLineIntersectionPoint(aPoint,
1059 Point(nRectLeft, nRectBottom), aRightHdg,
1060 rDiagPoint, aDiagHdg);
1061 // is there a point of intersection with the bottom border?
1062 if (aPoint.X() <= nRectRight)
1063 {
1064 nRight = aPoint.X();
1065 nBottom = nRectBottom;
1066 }
1067 else
1068 {
1069 // there has to be a point of intersection with the right border!
1070 GetLineIntersectionPoint(aPoint,
1071 Point(nRectRight, nRectTop), aDownHdg,
1072 rDiagPoint, aDiagHdg);
1073
1074 nRight = nRectRight;
1075 nBottom = aPoint.Y();
1076 }
1077 }
1078
1079 rSize = Size(nRight - nLeft + 1, nBottom - nTop + 1);
1080 rPos.setX( nLeft );
1081 rPos.setY( nTop );
1082}
1083
1084
1086{
1087 // Both arguments have to get into the SubNodes before the Operator so that clicking
1088 // within the GraphicWindow sets the FormulaCursor correctly (cf. SmRootNode)
1089 SmNode *pLeft = GetSubNode(0),
1090 *pRight = GetSubNode(1),
1091 *pLine = GetSubNode(2);
1092 assert(pLeft);
1093 assert(pRight);
1094 assert(pLine && pLine->GetType() == SmNodeType::PolyLine);
1095
1096 SmPolyLineNode *pOper = static_cast<SmPolyLineNode *>(pLine);
1097 assert(pOper);
1098
1102 SmTmpDevice aTmpDev (rDev, true);
1103 aTmpDev.SetFont(GetFont());
1104
1105 pLeft->Arrange(aTmpDev, rFormat);
1106 pRight->Arrange(aTmpDev, rFormat);
1107
1108 // determine implicitly the values (incl. the margin) of the diagonal line
1109 pOper->Arrange(aTmpDev, rFormat);
1110
1111 tools::Long nDelta = pOper->GetWidth() * 8 / 10;
1112
1113 // determine TopLeft position from the right argument
1114 Point aPos;
1115 aPos.setX( pLeft->GetItalicRight() + nDelta + pRight->GetItalicLeftSpace() );
1116 if (IsAscending())
1117 aPos.setY( pLeft->GetBottom() + nDelta );
1118 else
1119 aPos.setY( pLeft->GetTop() - nDelta - pRight->GetHeight() );
1120
1121 pRight->MoveTo(aPos);
1122
1123 // determine new baseline
1124 tools::Long nTmpBaseline = IsAscending() ? (pLeft->GetBottom() + pRight->GetTop()) / 2
1125 : (pLeft->GetTop() + pRight->GetBottom()) / 2;
1126 Point aLogCenter ((pLeft->GetItalicRight() + pRight->GetItalicLeft()) / 2,
1127 nTmpBaseline);
1128
1129 SmRect::operator = (*pLeft);
1130 ExtendBy(*pRight, RectCopyMBL::None);
1131
1132
1133 // determine position and size of diagonal line
1134 Size aTmpSize;
1135 GetOperPosSize(aPos, aTmpSize, aLogCenter, IsAscending() ? 60.0 : -60.0);
1136
1137 // font specialist advised to change the width first
1138 pOper->AdaptToY(aTmpDev, aTmpSize.Height());
1139 pOper->AdaptToX(aTmpDev, aTmpSize.Width());
1140 // and make it active
1141 pOper->Arrange(aTmpDev, rFormat);
1142
1143 pOper->MoveTo(aPos);
1144
1145 ExtendBy(*pOper, RectCopyMBL::None, nTmpBaseline);
1146}
1147
1148
1149/**************************************************************************/
1150
1151
1153{
1154 OSL_ENSURE(GetNumSubNodes() == 1 + SUBSUP_NUM_ENTRIES,
1155 "Sm: wrong number of subnodes");
1156
1157 SmNode *pBody = GetBody();
1158 assert(pBody);
1159
1160 tools::Long nOrigHeight = pBody->GetFont().GetFontSize().Height();
1161
1162 pBody->Arrange(rDev, rFormat);
1163
1164 const SmRect &rBodyRect = pBody->GetRect();
1165 SmRect::operator = (rBodyRect);
1166
1167 // line that separates sub- and supscript rectangles
1168 tools::Long nDelimLine = SmFromTo(GetAlignB(), GetAlignT(), 0.4);
1169
1170 Point aPos;
1171 tools::Long nDelta, nDist;
1172
1173 // iterate over all possible sub-/supscripts
1174 SmRect aTmpRect (rBodyRect);
1175 for (int i = 0; i < SUBSUP_NUM_ENTRIES; i++)
1176 {
1177 SmSubSup eSubSup = static_cast<SmSubSup>(i);
1178 SmNode *pSubSup = GetSubSup(eSubSup);
1179
1180 if (!pSubSup)
1181 continue;
1182
1183 // switch position of limits if we are in textmode
1184 if (rFormat.IsTextmode() && (GetToken().nGroup & TG::Limit))
1185 switch (eSubSup)
1186 { case CSUB: eSubSup = RSUB; break;
1187 case CSUP: eSubSup = RSUP; break;
1188 default:
1189 break;
1190 }
1191
1192 // prevent sub-/supscripts from diminishing in size
1193 // (as would be in "a_{1_{2_{3_4}}}")
1194 if (GetFont().GetFontSize().Height() > rFormat.GetBaseSize().Height() / 3)
1195 {
1196 sal_uInt16 nIndex = (eSubSup == CSUB || eSubSup == CSUP) ?
1198 Fraction aFraction ( rFormat.GetRelSize(nIndex), 100 );
1199 pSubSup->SetSize(aFraction);
1200 }
1201
1202 pSubSup->Arrange(rDev, rFormat);
1203
1204 bool bIsTextmode = rFormat.IsTextmode();
1205 nDist = 0;
1206
1208 switch (eSubSup)
1209 { case RSUB :
1210 case LSUB :
1211 if (!bIsTextmode)
1212 nDist = nOrigHeight
1213 * rFormat.GetDistance(DIS_SUBSCRIPT) / 100;
1214 aPos = pSubSup->GetRect().AlignTo(aTmpRect,
1215 eSubSup == LSUB ? RectPos::Left : RectPos::Right,
1217 aPos.AdjustY(nDist );
1218 nDelta = nDelimLine - aPos.Y();
1219 if (nDelta > 0)
1220 aPos.AdjustY(nDelta );
1221 break;
1222 case RSUP :
1223 case LSUP :
1224 if (!bIsTextmode)
1225 nDist = nOrigHeight
1226 * rFormat.GetDistance(DIS_SUPERSCRIPT) / 100;
1227 aPos = pSubSup->GetRect().AlignTo(aTmpRect,
1228 eSubSup == LSUP ? RectPos::Left : RectPos::Right,
1230 aPos.AdjustY( -nDist );
1231 nDelta = aPos.Y() + pSubSup->GetHeight() - nDelimLine;
1232 if (nDelta > 0)
1233 aPos.AdjustY( -nDelta );
1234 break;
1235 case CSUB :
1236 if (!bIsTextmode)
1237 nDist = nOrigHeight
1238 * rFormat.GetDistance(DIS_LOWERLIMIT) / 100;
1239 aPos = pSubSup->GetRect().AlignTo(rBodyRect, RectPos::Bottom,
1241 aPos.AdjustY(nDist );
1242 break;
1243 case CSUP :
1244 if (!bIsTextmode)
1245 nDist = nOrigHeight
1246 * rFormat.GetDistance(DIS_UPPERLIMIT) / 100;
1247 aPos = pSubSup->GetRect().AlignTo(rBodyRect, RectPos::Top,
1249 aPos.AdjustY( -nDist );
1250 break;
1251 }
1252
1253 pSubSup->MoveTo(aPos);
1254 ExtendBy(*pSubSup, RectCopyMBL::This, true);
1255
1256 // update rectangle to which RSUB, RSUP, LSUB, LSUP
1257 // will be aligned to
1258 if (eSubSup == CSUB || eSubSup == CSUP)
1259 aTmpRect = *this;
1260 }
1261}
1262
1263/**************************************************************************/
1264
1265void SmBraceNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
1266{
1267 SmNode *pLeft = OpeningBrace(),
1268 *pBody = Body(),
1269 *pRight = ClosingBrace();
1270 assert(pLeft);
1271 assert(pBody);
1272 assert(pRight);
1273
1274 pBody->Arrange(rDev, rFormat);
1275
1276 bool bIsScaleNormal = rFormat.IsScaleNormalBrackets(),
1277 bScale = pBody->GetHeight() > 0 &&
1278 (GetScaleMode() == SmScaleMode::Height || bIsScaleNormal),
1279 bIsABS = GetToken().eType == TABS;
1280
1281 tools::Long nFaceHeight = GetFont().GetFontSize().Height();
1282
1283 // determine oversize in %
1284 sal_uInt16 nPerc = 0;
1285 if (!bIsABS && bScale)
1286 { // in case of oversize braces...
1287 sal_uInt16 nIndex = GetScaleMode() == SmScaleMode::Height ?
1289 nPerc = rFormat.GetDistance(nIndex);
1290 }
1291
1292 // determine the height for the braces
1293 tools::Long nBraceHeight;
1294 if (bScale)
1295 {
1296 nBraceHeight = pBody->GetType() == SmNodeType::Bracebody ?
1297 static_cast<SmBracebodyNode *>(pBody)->GetBodyHeight()
1298 : pBody->GetHeight();
1299 nBraceHeight += 2 * (nBraceHeight * nPerc / 100);
1300 }
1301 else
1302 nBraceHeight = nFaceHeight;
1303
1304 // distance to the argument
1305 nPerc = bIsABS ? 0 : rFormat.GetDistance(DIS_BRACKETSPACE);
1306 tools::Long nDist = nFaceHeight * nPerc / 100;
1307
1308 // if wanted, scale the braces to the wanted size
1309 if (bScale)
1310 {
1311 Size aTmpSize (pLeft->GetFont().GetFontSize());
1312 OSL_ENSURE(pRight->GetFont().GetFontSize() == aTmpSize,
1313 "Sm : different font sizes");
1314 aTmpSize.setWidth( std::min(nBraceHeight * 60 / 100,
1315 rFormat.GetBaseSize().Height() * 3 / 2) );
1316 // correction factor since change from StarMath to OpenSymbol font
1317 // because of the different font width in the FontMetric
1318 aTmpSize.setWidth( aTmpSize.Width() * 182 );
1319 aTmpSize.setWidth( aTmpSize.Width() / 267 );
1320
1321 sal_Unicode cChar = pLeft->GetToken().cMathChar[0];
1322 if (cChar != MS_LINE && cChar != MS_DLINE &&
1323 cChar != MS_VERTLINE && cChar != MS_DVERTLINE)
1324 pLeft ->GetFont().SetSize(aTmpSize);
1325
1326 cChar = pRight->GetToken().cMathChar[0];
1327 if (cChar != MS_LINE && cChar != MS_DLINE &&
1328 cChar != MS_VERTLINE && cChar != MS_DVERTLINE)
1329 pRight->GetFont().SetSize(aTmpSize);
1330
1331 pLeft ->AdaptToY(rDev, nBraceHeight);
1332 pRight->AdaptToY(rDev, nBraceHeight);
1333 }
1334
1335 pLeft ->Arrange(rDev, rFormat);
1336 pRight->Arrange(rDev, rFormat);
1337
1338 // required in order to make "\‍(a\‍) - (a) - left ( a right )" look alright
1340
1341 Point aPos;
1342 aPos = pLeft->AlignTo(*pBody, RectPos::Left, RectHorAlign::Center, eVerAlign);
1343 aPos.AdjustX( -nDist );
1344 pLeft->MoveTo(aPos);
1345
1346 aPos = pRight->AlignTo(*pBody, RectPos::Right, RectHorAlign::Center, eVerAlign);
1347 aPos.AdjustX(nDist );
1348 pRight->MoveTo(aPos);
1349
1350 SmRect::operator = (*pBody);
1352}
1353
1354
1355/**************************************************************************/
1356
1357
1359{
1360 size_t nNumSubNodes = GetNumSubNodes();
1361 if (nNumSubNodes == 0)
1362 return;
1363
1364 // arrange arguments
1365 for (size_t i = 0; i < nNumSubNodes; i += 2)
1366 GetSubNode(i)->Arrange(rDev, rFormat);
1367
1368 // build reference rectangle with necessary info for vertical alignment
1369 SmRect aRefRect (*GetSubNode(0));
1370 for (size_t i = 0; i < nNumSubNodes; i += 2)
1371 {
1372 SmRect aTmpRect (*GetSubNode(i));
1374 aTmpRect.MoveTo(aPos);
1375 aRefRect.ExtendBy(aTmpRect, RectCopyMBL::Xor);
1376 }
1377
1378 mnBodyHeight = aRefRect.GetHeight();
1379
1380 // scale separators to required height and arrange them
1381 bool bScale = GetScaleMode() == SmScaleMode::Height || rFormat.IsScaleNormalBrackets();
1382 tools::Long nHeight = bScale ? aRefRect.GetHeight() : GetFont().GetFontSize().Height();
1383 sal_uInt16 nIndex = GetScaleMode() == SmScaleMode::Height ?
1385 sal_uInt16 nPerc = rFormat.GetDistance(nIndex);
1386 if (bScale)
1387 nHeight += 2 * (nHeight * nPerc / 100);
1388 for (size_t i = 1; i < nNumSubNodes; i += 2)
1389 {
1390 SmNode *pNode = GetSubNode(i);
1391 pNode->AdaptToY(rDev, nHeight);
1392 pNode->Arrange(rDev, rFormat);
1393 }
1394
1395 // horizontal distance between argument and brackets or separators
1397 * rFormat.GetDistance(DIS_BRACKETSPACE) / 100;
1398
1399 SmNode *pLeft = GetSubNode(0);
1400 SmRect::operator = (*pLeft);
1401 for (size_t i = 1; i < nNumSubNodes; ++i)
1402 {
1403 bool bIsSeparator = i % 2 != 0;
1404 RectVerAlign eVerAlign = bIsSeparator ? RectVerAlign::CenterY : RectVerAlign::Baseline;
1405
1406 SmNode *pRight = GetSubNode(i);
1407 Point aPosX = pRight->AlignTo(*pLeft, RectPos::Right, RectHorAlign::Center, eVerAlign),
1408 aPosY = pRight->AlignTo(aRefRect, RectPos::Right, RectHorAlign::Center, eVerAlign);
1409 aPosX.AdjustX(nDist );
1410
1411 pRight->MoveTo(Point(aPosX.X(), aPosY.Y()));
1412 ExtendBy(*pRight, bIsSeparator ? RectCopyMBL::This : RectCopyMBL::Xor);
1413
1414 pLeft = pRight;
1415 }
1416}
1417
1418
1419/**************************************************************************/
1420
1421
1423{
1424 SmNode *pBody = Body(),
1425 *pBrace = Brace(),
1426 *pScript = Script();
1427 assert(pBody);
1428 assert(pBrace);
1429 assert(pScript);
1430
1431 SmTmpDevice aTmpDev (rDev, true);
1432 aTmpDev.SetFont(GetFont());
1433
1434 pBody->Arrange(aTmpDev, rFormat);
1435
1436 // size is the same as for limits for this part
1437 pScript->SetSize( Fraction( rFormat.GetRelSize(SIZ_LIMITS), 100 ) );
1438 // braces are a bit taller than usually
1439 pBrace ->SetSize( Fraction(3, 2) );
1440
1441 tools::Long nItalicWidth = pBody->GetItalicWidth();
1442 if (nItalicWidth > 0)
1443 pBrace->AdaptToX(aTmpDev, nItalicWidth);
1444
1445 pBrace ->Arrange(aTmpDev, rFormat);
1446 pScript->Arrange(aTmpDev, rFormat);
1447
1448 // determine the relative position and the distances between each other
1449 RectPos eRectPos;
1450 tools::Long nFontHeight = pBody->GetFont().GetFontSize().Height();
1451 tools::Long nDistBody = nFontHeight * rFormat.GetDistance(DIS_ORNAMENTSIZE),
1452 nDistScript = nFontHeight;
1453 if (GetToken().eType == TOVERBRACE)
1454 {
1455 eRectPos = RectPos::Top;
1456 nDistBody = - nDistBody;
1457 nDistScript *= - rFormat.GetDistance(DIS_UPPERLIMIT);
1458 }
1459 else // TUNDERBRACE
1460 {
1461 eRectPos = RectPos::Bottom;
1462 nDistScript *= + rFormat.GetDistance(DIS_LOWERLIMIT);
1463 }
1464 nDistBody /= 100;
1465 nDistScript /= 100;
1466
1467 Point aPos = pBrace->AlignTo(*pBody, eRectPos, RectHorAlign::Center, RectVerAlign::Baseline);
1468 aPos.AdjustY(nDistBody );
1469 pBrace->MoveTo(aPos);
1470
1471 aPos = pScript->AlignTo(*pBrace, eRectPos, RectHorAlign::Center, RectVerAlign::Baseline);
1472 aPos.AdjustY(nDistScript );
1473 pScript->MoveTo(aPos);
1474
1475 SmRect::operator = (*pBody);
1477}
1478
1479
1480/**************************************************************************/
1481
1482
1484{
1485 SmNode *pNode = GetSubNode(0);
1486 assert(pNode);
1487
1488 if (pNode->GetType() == SmNodeType::SubSup)
1489 pNode = static_cast<SmSubSupNode *>(pNode)->GetBody();
1490
1491 OSL_ENSURE(pNode, "Sm: NULL pointer!");
1492 return pNode;
1493}
1494
1495
1497 const SmFormat &rFormat) const
1498 // returns the font height to be used for operator-symbol
1499{
1500 tools::Long nHeight = GetFont().GetFontSize().Height();
1501
1502 SmTokenType eTmpType = GetToken().eType;
1503 if (eTmpType == TLIM || eTmpType == TLIMINF || eTmpType == TLIMSUP)
1504 return nHeight;
1505
1506 if (!rFormat.IsTextmode())
1507 {
1508 // set minimum size ()
1509 nHeight += (nHeight * 20) / 100;
1510
1511 nHeight += nHeight
1512 * rFormat.GetDistance(DIS_OPERATORSIZE) / 100;
1513 nHeight = nHeight * 686 / 845;
1514 }
1515
1516 // correct user-defined symbols to match height of sum from used font
1517 if (rSymbol.GetToken().eType == TSPECIAL)
1518 nHeight = nHeight * 845 / 686;
1519
1520 return nHeight;
1521}
1522
1523
1524void SmOperNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
1525{
1526 SmNode *pOper = GetSubNode(0);
1527 SmNode *pBody = GetSubNode(1);
1528
1529 assert(pOper);
1530 assert(pBody);
1531
1532 SmNode *pSymbol = GetSymbol();
1533 pSymbol->SetSize(Fraction(CalcSymbolHeight(*pSymbol, rFormat),
1534 pSymbol->GetFont().GetFontSize().Height()));
1535
1536 pBody->Arrange(rDev, rFormat);
1537 bool bDynamicallySized = false;
1538 if (pSymbol->GetToken().eType == TINTD)
1539 {
1540 tools::Long nBodyHeight = pBody->GetHeight();
1541 tools::Long nFontHeight = pSymbol->GetFont().GetFontSize().Height();
1542 if (nFontHeight < nBodyHeight)
1543 {
1544 pSymbol->SetSize(Fraction(nBodyHeight, nFontHeight));
1545 bDynamicallySized = true;
1546 }
1547 }
1548 pOper->Arrange(rDev, rFormat);
1549
1550 tools::Long nOrigHeight = GetFont().GetFontSize().Height(),
1551 nDist = nOrigHeight
1552 * rFormat.GetDistance(DIS_OPERATORSPACE) / 100;
1553
1554 Point aPos = pOper->AlignTo(*pBody, RectPos::Left, RectHorAlign::Center, bDynamicallySized ? RectVerAlign::CenterY : RectVerAlign::Mid);
1555 aPos.AdjustX( -nDist );
1556 pOper->MoveTo(aPos);
1557
1558 SmRect::operator = (*pBody);
1559 ExtendBy(*pOper, RectCopyMBL::This);
1560}
1561
1562
1563/**************************************************************************/
1564
1565
1566void SmAlignNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
1567 // set alignment within the entire subtree (including current node)
1568{
1569 assert(GetNumSubNodes() == 1);
1570
1571 SmNode *pNode = GetSubNode(0);
1572 assert(pNode);
1573
1575 switch (GetToken().eType)
1576 {
1577 case TALIGNL: eHorAlign = RectHorAlign::Left; break;
1578 case TALIGNC: eHorAlign = RectHorAlign::Center; break;
1579 case TALIGNR: eHorAlign = RectHorAlign::Right; break;
1580 default:
1581 break;
1582 }
1583 SetRectHorAlign(eHorAlign);
1584
1585 pNode->Arrange(rDev, rFormat);
1586
1587 SmRect::operator = (pNode->GetRect());
1588}
1589
1590
1591/**************************************************************************/
1592
1593
1595{
1596 SmNode *pAttr = Attribute(),
1597 *pBody = Body();
1598 assert(pBody);
1599 assert(pAttr);
1600
1601 pBody->Arrange(rDev, rFormat);
1602
1604 pAttr->AdaptToX(rDev, pBody->GetItalicWidth());
1605 pAttr->Arrange(rDev, rFormat);
1606
1607 // get relative position of attribute
1608 RectVerAlign eVerAlign;
1609 tools::Long nDist = 0;
1610 switch (GetToken().eType)
1611 { case TUNDERLINE :
1612 eVerAlign = RectVerAlign::AttributeLo;
1613 break;
1614 case TOVERSTRIKE :
1615 eVerAlign = RectVerAlign::AttributeMid;
1616 break;
1617 default :
1618 eVerAlign = RectVerAlign::AttributeHi;
1619 if (pBody->GetType() == SmNodeType::Attribute)
1620 nDist = GetFont().GetFontSize().Height()
1621 * rFormat.GetDistance(DIS_ORNAMENTSPACE) / 100;
1622 }
1623 Point aPos = pAttr->AlignTo(*pBody, RectPos::Attribute, RectHorAlign::Center, eVerAlign);
1624 aPos.AdjustY( -nDist );
1625 pAttr->MoveTo(aPos);
1626
1627 SmRect::operator = (*pBody);
1628 ExtendBy(*pAttr, RectCopyMBL::This, true);
1629}
1630
1631void SmFontNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
1632{
1634 SmNode::Prepare(rFormat, rDocShell, nDepth);
1635
1636 int nFnt = -1;
1637 switch (GetToken().eType)
1638 {
1639 case TFIXED: nFnt = FNT_FIXED; break;
1640 case TSANS: nFnt = FNT_SANS; break;
1641 case TSERIF: nFnt = FNT_SERIF; break;
1642 default:
1643 break;
1644 }
1645 if (nFnt != -1)
1646 { GetFont() = rFormat.GetFont( sal::static_int_cast< sal_uInt16 >(nFnt) );
1647 SetFont(GetFont());
1648 }
1649
1653}
1654
1655void SmFontNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
1656{
1657 SmNode *pNode = GetSubNode(1);
1658 assert(pNode);
1659 sal_uInt32 nc;
1660
1661 switch (GetToken().eType)
1662 { case TSIZE :
1664 break;
1665 case TSANS :
1666 case TSERIF :
1667 case TFIXED :
1668 pNode->SetFont(GetFont());
1669 break;
1670 case TUNKNOWN : break; // no assertion on "font <?> <?>"
1671
1672 case TPHANTOM : SetPhantom(true); break;
1673 case TBOLD : SetAttribute(FontAttribute::Bold); break;
1677
1678 // Using HTML CSS Level 1 standard
1679 case TRGB :
1680 case TRGBA :
1681 case THTMLCOL :
1682 case TMATHMLCOL :
1683 case TDVIPSNAMESCOL:
1684 case TICONICCOL :
1685 case THEX :
1686 nc = GetToken().cMathChar.toUInt32(16);
1688 break;
1689
1690 default:
1691 SAL_WARN("starmath", "unknown case");
1692 }
1693
1694 pNode->Arrange(rDev, rFormat);
1695
1696 SmRect::operator = (pNode->GetRect());
1697}
1698
1699/**************************************************************************/
1700
1701
1703 : SmGraphicNode(SmNodeType::PolyLine, rNodeToken)
1704 , maPoly(2)
1705 , mnWidth(0)
1706{
1707}
1708
1709
1711{
1712 maToSize.setWidth( nNewWidth );
1713}
1714
1715
1717{
1719 maToSize.setHeight( nNewHeight );
1720}
1721
1722
1724{
1728 SmTmpDevice aTmpDev (rDev, true);
1729 aTmpDev.SetFont(GetFont());
1730
1731 tools::Long nBorderwidth = GetFont().GetBorderWidth();
1732
1733 // create polygon using both endpoints
1734 assert(maPoly.GetSize() == 2);
1735 Point aPointA, aPointB;
1736 if (GetToken().eType == TWIDESLASH)
1737 {
1738 aPointA.setX( nBorderwidth );
1739 aPointA.setY( maToSize.Height() - nBorderwidth );
1740 aPointB.setX( maToSize.Width() - nBorderwidth );
1741 aPointB.setY( nBorderwidth );
1742 }
1743 else
1744 {
1745 OSL_ENSURE(GetToken().eType == TWIDEBACKSLASH, "Sm : unexpected token");
1746 aPointA.setX( nBorderwidth );
1747 aPointA.setY( nBorderwidth );
1748 aPointB.setX( maToSize.Width() - nBorderwidth );
1749 aPointB.setY( maToSize.Height() - nBorderwidth );
1750 }
1751 maPoly.SetPoint(aPointA, 0);
1752 maPoly.SetPoint(aPointB, 1);
1753
1754 tools::Long nThick = GetFont().GetFontSize().Height()
1755 * rFormat.GetDistance(DIS_STROKEWIDTH) / 100;
1756 mnWidth = nThick + 2 * nBorderwidth;
1757
1758 SmRect::operator = (SmRect(maToSize.Width(), maToSize.Height()));
1759}
1760
1761
1762/**************************************************************************/
1763
1765{
1766 mnBodyWidth = nWidth;
1767}
1768
1769
1771{
1772 // some additional length so that the horizontal
1773 // bar will be positioned above the argument
1774 SmMathSymbolNode::AdaptToY(rDev, nHeight + nHeight / 10);
1775}
1776
1777
1778/**************************************************************************/
1779
1780
1782{
1783 maToSize.setWidth( nWidth );
1784}
1785
1786
1788{
1790 maToSize.setHeight( nHeight );
1791}
1792
1793
1794void SmRectangleNode::Arrange(OutputDevice &rDev, const SmFormat &/*rFormat*/)
1795{
1796 tools::Long nFontHeight = GetFont().GetFontSize().Height();
1797 tools::Long nWidth = maToSize.Width(),
1798 nHeight = maToSize.Height();
1799 if (nHeight == 0)
1800 nHeight = nFontHeight / 30;
1801 if (nWidth == 0)
1802 nWidth = nFontHeight / 3;
1803
1804 SmTmpDevice aTmpDev (rDev, true);
1805 aTmpDev.SetFont(GetFont());
1806
1807 // add some borderspace
1808 sal_uLong nTmpBorderWidth = GetFont().GetBorderWidth();
1809 nHeight += 2 * nTmpBorderWidth;
1810
1813 SmRect::operator = (SmRect(nWidth, nHeight));
1814}
1815
1816
1817/**************************************************************************/
1818
1819
1820SmTextNode::SmTextNode( SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 nFontDescP )
1821 : SmVisibleNode(eNodeType, rNodeToken)
1822 , mnFontDesc(nFontDescP)
1823 , mnSelectionStart(0)
1824 , mnSelectionEnd(0)
1825{
1826}
1827
1828SmTextNode::SmTextNode( const SmToken &rNodeToken, sal_uInt16 nFontDescP )
1829 : SmVisibleNode(SmNodeType::Text, rNodeToken)
1830 , mnFontDesc(nFontDescP)
1831 , mnSelectionStart(0)
1832 , mnSelectionEnd(0)
1833{
1834}
1835
1836void SmTextNode::ChangeText(const OUString &rText) {
1837 maText = rText;
1838 GetToken().aText = rText;
1840}
1841
1842void SmTextNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
1843{
1844 SmNode::Prepare(rFormat, rDocShell, nDepth);
1845
1846 // default setting for horizontal alignment of nodes with TTEXT
1847 // content is as alignl (cannot be done in Arrange since it would
1848 // override the settings made by an SmAlignNode before)
1849 if (TTEXT == GetToken().eType)
1851
1852 maText = GetToken().aText;
1853 GetFont() = rFormat.GetFont(GetFontDesc());
1854
1855 if (IsItalic( GetFont() ))
1857 if (IsBold( GetFont() ))
1859
1860 // special handling for ':' where it is a token on its own and is likely
1861 // to be used for mathematical notations. (E.g. a:b = 2:3)
1862 // In that case it should not be displayed in italic.
1863 if (GetToken().aText.getLength() == 1 && GetToken().aText[0] == ':')
1864 Attributes() &= ~FontAttribute::Italic;
1865};
1866
1867
1868void SmTextNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
1869{
1871
1872 sal_uInt16 nSizeDesc = GetFontDesc() == FNT_FUNCTION ?
1874 GetFont() *= Fraction (rFormat.GetRelSize(nSizeDesc), 100);
1875
1876 SmTmpDevice aTmpDev (rDev, true);
1877 aTmpDev.SetFont(GetFont());
1878
1879 SmRect::operator = (SmRect(aTmpDev, &rFormat, maText, GetFont().GetBorderWidth()));
1880}
1881
1882void SmTextNode::GetAccessibleText( OUStringBuffer &rText ) const
1883{
1884 rText.append(maText);
1885}
1886
1888{
1889 if (GetToken().nGroup == TG::Function) mnFontDesc = FNT_FUNCTION;
1890 else if (GetToken().eType == TTEXT) mnFontDesc = FNT_TEXT;
1891 else {
1892 sal_Unicode firstChar = maText[0];
1893 if( ('0' <= firstChar && firstChar <= '9') || firstChar == '.' || firstChar == ',')
1895 else mnFontDesc = FNT_VARIABLE;
1896 }
1897}
1898
1900{
1901 //Find the best match in accepted unicode for our private area symbols
1902 static const sal_Unicode aStarMathPrivateToUnicode[] =
1903 {
1904 0x2030, 0xF613, 0xF612, 0x002B, 0x003C, 0x003E, 0xE425, 0xE421, 0xE088, 0x2208,
1905 0x0192, 0x2026, 0x2192, 0x221A, 0x221A, 0x221A, 0xE090, 0x005E, 0x02C7, 0x02D8,
1906 0x00B4, 0x0060, 0x02DC, 0x00AF, 0x0362, 0xE099, 0xE09A, 0x20DB, 0xE09C, 0xE09D,
1907 0x0028, 0x0029, 0x2220, 0x22AF, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7,
1908 0x002F, 0x005C, 0x274F, 0xE0AB, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03A0,
1909 0x03a3, 0x03a5, 0x03a6, 0x03a8, 0x03A9, 0x03B1, 0x03B2, 0x03b3, 0x03b4, 0x03b5,
1910 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
1911 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03b5,
1912 0x03d1, 0x03d6, 0xE0D2, 0x03db, 0x2118, 0x2202, 0x2129, 0xE0D7, 0xE0D8, 0x22A4,
1913 0xE0DA, 0x2190, 0x2191, 0x2193
1914 };
1915 if ((nIn >= 0xE080) && (nIn <= 0xE0DD))
1916 nIn = aStarMathPrivateToUnicode[nIn-0xE080];
1917
1918 //For whatever unicode glyph that equation editor doesn't ship with that
1919 //we have a possible match we can munge it to.
1920 switch (nIn)
1921 {
1922 case 0x2223:
1923 nIn = '|';
1924 break;
1925 default:
1926 break;
1927 }
1928
1929 return nIn;
1930}
1931
1932/**************************************************************************/
1933
1935{
1936 SmNode *pNode;
1937
1938 // initialize array that is to hold the maximum widths of all
1939 // elements (subnodes) in that column.
1940 std::vector<tools::Long> aColWidth(mnNumCols);
1941
1942 // arrange subnodes and calculate the above arrays contents
1943 size_t nNodes = GetNumSubNodes();
1944 for (size_t i = 0; i < nNodes; ++i)
1945 {
1946 size_t nIdx = nNodes - 1 - i;
1947 if (nullptr != (pNode = GetSubNode(nIdx)))
1948 {
1949 pNode->Arrange(rDev, rFormat);
1950 int nCol = nIdx % mnNumCols;
1951 aColWidth[nCol] = std::max(aColWidth[nCol], pNode->GetItalicWidth());
1952 }
1953 }
1954
1955 // norm distance from which the following two are calculated
1956 const tools::Long nNormDist = 3 * GetFont().GetFontSize().Height();
1957
1958 // define horizontal and vertical minimal distances that separate
1959 // the elements
1960 tools::Long nHorDist = nNormDist * rFormat.GetDistance(DIS_MATRIXCOL) / 100,
1961 nVerDist = nNormDist * rFormat.GetDistance(DIS_MATRIXROW) / 100;
1962
1963 // build array that holds the leftmost position for each column
1964 std::vector<tools::Long> aColLeft(mnNumCols);
1965 tools::Long nX = 0;
1966 for (size_t j = 0; j < mnNumCols; ++j)
1967 {
1968 aColLeft[j] = nX;
1969 nX += aColWidth[j] + nHorDist;
1970 }
1971
1972 SmRect::operator = (SmRect());
1973 for (size_t i = 0; i < mnNumRows; ++i)
1974 {
1975 Point aPos;
1976 SmRect aLineRect;
1977 for (size_t j = 0; j < mnNumCols; ++j)
1978 {
1979 SmNode *pTmpNode = GetSubNode(i * mnNumCols + j);
1980 assert(pTmpNode);
1981
1982 const SmRect &rNodeRect = pTmpNode->GetRect();
1983
1984 // align all baselines in that row if possible
1986
1987 // get horizontal alignment
1988 const SmNode *pCoNode = pTmpNode->GetLeftMost();
1989 RectHorAlign eHorAlign = pCoNode->GetRectHorAlign();
1990
1991 // calculate horizontal position of element depending on column
1992 // and horizontal alignment
1993 switch (eHorAlign)
1994 { case RectHorAlign::Left:
1995 aPos.setX( aColLeft[j] );
1996 break;
1998 aPos.setX( rNodeRect.GetLeft() + aColLeft[j]
1999 + aColWidth[j] / 2
2000 - rNodeRect.GetItalicCenterX() );
2001 break;
2003 aPos.setX( aColLeft[j]
2004 + aColWidth[j] - rNodeRect.GetItalicWidth() );
2005 break;
2006 default:
2007 assert(false);
2008 }
2009
2010 pTmpNode->MoveTo(aPos);
2011 aLineRect.ExtendBy(rNodeRect, RectCopyMBL::Xor);
2012 }
2013
2015 if (i > 0)
2016 aPos.AdjustY(nVerDist );
2017
2018 // move 'aLineRect' and rectangles in that line to final position
2019 Point aDelta(0, // since horizontal alignment is already done
2020 aPos.Y() - aLineRect.GetTop());
2021 aLineRect.Move(aDelta);
2022 for (size_t j = 0; j < mnNumCols; ++j)
2023 {
2024 if (nullptr != (pNode = GetSubNode(i * mnNumCols + j)))
2025 pNode->Move(aDelta);
2026 }
2027
2028 ExtendBy(aLineRect, RectCopyMBL::None);
2029 }
2030}
2031
2033{
2034 return this;
2035}
2036
2037
2038/**************************************************************************/
2039
2040
2042: SmSpecialNode(SmNodeType::Math, rNodeToken, FNT_MATH)
2043{
2044 SetText(GetToken().cMathChar);
2045}
2046
2048{
2049 // Since there is no function to do this, we try to approximate it:
2050 Size aFntSize (GetFont().GetFontSize());
2051
2053 aFntSize.setWidth( nWidth );
2054 GetFont().SetSize(aFntSize);
2055
2056 SmTmpDevice aTmpDev (rDev, true);
2057 aTmpDev.SetFont(GetFont());
2058
2059 // get denominator of error factor for width
2060 tools::Long nTmpBorderWidth = GetFont().GetBorderWidth();
2061 tools::Long nDenom = SmRect(aTmpDev, nullptr, GetText(), nTmpBorderWidth).GetItalicWidth();
2062
2063 // scale fontwidth with this error factor
2064 aFntSize.setWidth( aFntSize.Width() * nWidth );
2065 aFntSize.setWidth( aFntSize.Width() / ( nDenom ? nDenom : 1) );
2066
2067 GetFont().SetSize(aFntSize);
2068}
2069
2071{
2073 Size aFntSize (GetFont().GetFontSize());
2074
2075 // Since we only want to scale the height, we might have
2076 // to determine the font width in order to keep it
2077 if (aFntSize.Width() == 0)
2078 {
2080 rDev.SetFont(GetFont());
2081 aFntSize.setWidth( rDev.GetFontMetric().GetFontSize().Width() );
2082 rDev.Pop();
2083 }
2084 OSL_ENSURE(aFntSize.Width() != 0, "Sm: ");
2085
2088 aFntSize.setHeight( nHeight );
2089 GetFont().SetSize(aFntSize);
2090
2091 SmTmpDevice aTmpDev (rDev, true);
2092 aTmpDev.SetFont(GetFont());
2093
2094 // get denominator of error factor for height
2095 tools::Long nTmpBorderWidth = GetFont().GetBorderWidth();
2096 tools::Long nDenom = 0;
2097 if (!GetText().isEmpty())
2098 nDenom = SmRect(aTmpDev, nullptr, GetText(), nTmpBorderWidth).GetHeight();
2099
2100 // scale fontwidth with this error factor
2101 aFntSize.setHeight( aFntSize.Height() * nHeight );
2102 aFntSize.setHeight( aFntSize.Height() / ( nDenom ? nDenom : 1) );
2103
2104 GetFont().SetSize(aFntSize);
2105}
2106
2107
2108void SmMathSymbolNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
2109{
2110 SmNode::Prepare(rFormat, rDocShell, nDepth);
2111
2112 GetFont() = rFormat.GetFont(GetFontDesc());
2113 // use same font size as is used for variables
2115
2116 OSL_ENSURE(GetFont().GetCharSet() == RTL_TEXTENCODING_SYMBOL ||
2117 GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE,
2118 "wrong charset for character from StarMath/OpenSymbol font");
2119
2121};
2122
2123
2125{
2126 const OUString &rText = GetText();
2127
2128 if (rText.isEmpty() || rText[0] == '\0')
2129 { SmRect::operator = (SmRect());
2130 return;
2131 }
2132
2134
2135 GetFont() *= Fraction (rFormat.GetRelSize(SIZ_TEXT), 100);
2136
2137 SmTmpDevice aTmpDev (rDev, true);
2138 aTmpDev.SetFont(GetFont());
2139
2140 SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth()));
2141}
2142
2143/**************************************************************************/
2144
2145static bool lcl_IsFromGreekSymbolSet( std::u16string_view aTokenText )
2146{
2147 bool bRes = false;
2148
2149 // valid symbol name needs to have a '%' at pos 0 and at least an additional char
2150 if (aTokenText.size() > 2 && aTokenText[0] == u'%')
2151 {
2152 OUString aName( aTokenText.substr(1) );
2153 SmSym *pSymbol = SM_MOD()->GetSymbolManager().GetSymbolByName( aName );
2154 if (pSymbol && SmLocalizedSymbolData::GetExportSymbolSetName(pSymbol->GetSymbolSetName()) == "Greek")
2155 bRes = true;
2156 }
2157
2158 return bRes;
2159}
2160
2161
2162SmSpecialNode::SmSpecialNode(SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 _nFontDesc)
2163 : SmTextNode(eNodeType, rNodeToken, _nFontDesc)
2164 , mbIsFromGreekSymbolSet(lcl_IsFromGreekSymbolSet( rNodeToken.aText ))
2165{
2166}
2167
2168
2170 : SmTextNode(SmNodeType::Special, rNodeToken, FNT_MATH) // default Font isn't always correct!
2171 , mbIsFromGreekSymbolSet(lcl_IsFromGreekSymbolSet( rNodeToken.aText ))
2172{
2173}
2174
2175
2176void SmSpecialNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
2177{
2178 SmNode::Prepare(rFormat, rDocShell, nDepth);
2179
2180 const SmSym *pSym;
2181 SmModule *pp = SM_MOD();
2182
2183 OUString aName(GetToken().aText.copy(1));
2184 if (nullptr != (pSym = pp->GetSymbolManager().GetSymbolByName( aName )))
2185 {
2186 sal_UCS4 cChar = pSym->GetCharacter();
2187 OUString aTmp( &cChar, 1 );
2188 SetText( aTmp );
2189 GetFont() = pSym->GetFace();
2190 }
2191 else
2192 {
2193 SetText( GetToken().aText );
2194 GetFont() = rFormat.GetFont(FNT_VARIABLE);
2195 }
2196 // use same font size as is used for variables
2198
2199 // Actually only WEIGHT_NORMAL and WEIGHT_BOLD should occur... However, the sms-file also
2200 // contains e.g. 'WEIGHT_ULTRALIGHT'. Consequently, compare here with '>' instead of '!='.
2201 // (In the long term the necessity for 'PrepareAttribut' and thus also for this here should be dropped)
2202
2204 if (IsItalic( GetFont() ))
2206 if (IsBold( GetFont() ))
2208
2210
2212 return;
2213
2214 OSL_ENSURE( GetText().getLength() == 1, "a symbol should only consist of 1 char!" );
2215 bool bItalic = false;
2216 sal_Int16 nStyle = rFormat.GetGreekCharStyle();
2217 OSL_ENSURE( nStyle >= 0 && nStyle <= 2, "unexpected value for GreekCharStyle" );
2218 if (nStyle == 1)
2219 bItalic = true;
2220 else if (nStyle == 2)
2221 {
2222 const OUString& rTmp(GetText());
2223 if (!rTmp.isEmpty())
2224 {
2225 static const sal_Unicode cUppercaseAlpha = 0x0391;
2226 static const sal_Unicode cUppercaseOmega = 0x03A9;
2227 sal_Unicode cChar = rTmp[0];
2228 // uppercase letters should be straight and lowercase letters italic
2229 bItalic = cUppercaseAlpha > cChar || cChar > cUppercaseOmega;
2230 }
2231 }
2232
2233 if (bItalic)
2235 else
2236 Attributes() &= ~FontAttribute::Italic;
2237};
2238
2239
2241{
2243
2244 SmTmpDevice aTmpDev (rDev, true);
2245 aTmpDev.SetFont(GetFont());
2246
2247 SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth()));
2248}
2249
2250/**************************************************************************/
2251
2252
2254{
2256
2257 SmTmpDevice aTmpDev (rDev, true);
2258 aTmpDev.SetFont(GetFont());
2259
2260 SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(),
2262}
2263
2264
2265/**************************************************************************/
2266
2267
2268void SmPlaceNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
2269{
2270 SmNode::Prepare(rFormat, rDocShell, nDepth);
2271
2274};
2275
2276
2277void SmPlaceNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
2278{
2280
2281 SmTmpDevice aTmpDev (rDev, true);
2282 aTmpDev.SetFont(GetFont());
2283
2284 SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth()));
2285}
2286
2287
2288/**************************************************************************/
2289
2290
2291void SmErrorNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
2292{
2293 SmNode::Prepare(rFormat, rDocShell, nDepth);
2294
2298}
2299
2300
2301void SmErrorNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
2302{
2304
2305 SmTmpDevice aTmpDev (rDev, true);
2306 aTmpDev.SetFont(GetFont());
2307
2308 const OUString &rText = GetText();
2309 SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth()));
2310}
2311
2312/**************************************************************************/
2313
2314void SmBlankNode::IncreaseBy(const SmToken &rToken, sal_uInt32 nMultiplyBy)
2315{
2316 switch(rToken.eType)
2317 {
2318 case TBLANK: mnNum += (4 * nMultiplyBy); break;
2319 case TSBLANK: mnNum += (1 * nMultiplyBy); break;
2320 default:
2321 break;
2322 }
2323}
2324
2325void SmBlankNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
2326{
2327 SmNode::Prepare(rFormat, rDocShell, nDepth);
2328
2329 // Here it need/should not be the StarMath font, so that for the character
2330 // used in Arrange a normal (non-clipped) rectangle is generated
2331 GetFont() = rFormat.GetFont(FNT_VARIABLE);
2332
2334}
2335
2336
2337void SmBlankNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
2338{
2339 SmTmpDevice aTmpDev (rDev, true);
2340 aTmpDev.SetFont(GetFont());
2341
2342 // make distance depend on the font height
2343 // (so that it increases when scaling (e.g. size *2 {a ~ b})
2344 tools::Long nDist = GetFont().GetFontSize().Height() / 10,
2345 nSpace = mnNum * nDist;
2346
2347 // get a SmRect with Baseline and all the bells and whistles
2348 SmRect::operator = (SmRect(aTmpDev, &rFormat, OUString(' '),
2349 GetFont().GetBorderWidth()));
2350
2351 // and resize it to the requested size
2352 SetItalicSpaces(0, 0);
2353 SetWidth(nSpace);
2354}
2355
2356/**************************************************************************/
2357//Implementation of all accept methods for SmVisitor
2358
2360 pVisitor->Visit(this);
2361}
2362
2364 pVisitor->Visit(this);
2365}
2366
2368 pVisitor->Visit(this);
2369}
2370
2372 pVisitor->Visit(this);
2373}
2374
2376 pVisitor->Visit(this);
2377}
2378
2380 pVisitor->Visit(this);
2381}
2382
2384 pVisitor->Visit(this);
2385}
2386
2388 pVisitor->Visit(this);
2389}
2390
2392 pVisitor->Visit(this);
2393}
2394
2396 pVisitor->Visit(this);
2397}
2398
2400 pVisitor->Visit(this);
2401}
2402
2404 pVisitor->Visit(this);
2405}
2406
2408 pVisitor->Visit(this);
2409}
2410
2412 pVisitor->Visit(this);
2413}
2414
2416 pVisitor->Visit(this);
2417}
2418
2420 pVisitor->Visit(this);
2421}
2422
2424 pVisitor->Visit(this);
2425}
2426
2428 pVisitor->Visit(this);
2429}
2430
2432 pVisitor->Visit(this);
2433}
2434
2436 pVisitor->Visit(this);
2437}
2438
2440 pVisitor->Visit(this);
2441}
2442
2444 pVisitor->Visit(this);
2445}
2446
2448 pVisitor->Visit(this);
2449}
2450
2452 pVisitor->Visit(this);
2453}
2454
2456 pVisitor->Visit(this);
2457}
2458
2460 pVisitor->Visit(this);
2461}
2462
2464 pVisitor->Visit(this);
2465}
2466
2467/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool mbIsSelected
Fraction conversionFract(o3tl::Length from, o3tl::Length to)
constexpr auto DBL_EPSILON
void SetFont(const vcl::Font &rNewFont)
FontMetric GetFontMetric() const
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
constexpr tools::Long Y() const
void setX(tools::Long nX)
void setY(tools::Long nY)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
constexpr tools::Long Height() const
tools::Long AdjustHeight(tools::Long n)
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1566
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2375
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1594
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2379
const SmNode * Body() const
Gets the body data ( the nodes affected by the attribute ).
Definition: node.hxx:1922
const SmNode * Attribute() const
Gets the attribute data.
Definition: node.hxx:1915
void GetOperPosSize(Point &rPos, Size &rSize, const Point &rDiagPoint, double fAngleDeg) const
Returns the position and size of the diagonal line by reference.
Definition: node.cxx:974
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2399
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1085
bool IsAscending() const
Checks if it is of ascending type.
Definition: node.hxx:1491
const SmNode * Symbol() const
Returns the node containing the data of the binary operator.
Definition: node.hxx:1393
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:795
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2391
const SmNode * LeftOperand() const
Returns the node containing the data of the left operand.
Definition: node.hxx:1400
const SmNode * RightOperand() const
Returns the node containing the data of the right operand.
Definition: node.hxx:1407
virtual const SmNode * GetLeftMost() const override
(this assumes the one with index 0 is always the leftmost subnode for the current node).
Definition: node.cxx:897
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2395
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:840
sal_uInt16 mnNum
Definition: node.hxx:2057
void IncreaseBy(const SmToken &rToken, sal_uInt32 nMultiplyBy=1)
Definition: node.cxx:2314
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2431
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
Definition: node.cxx:2325
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:2337
const SmMathSymbolNode * OpeningBrace() const
Returns the node containing the data of the opening brace.
Definition: node.hxx:1655
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1265
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2363
const SmNode * Body() const
Returns the node containing the data of what is between braces.
Definition: node.hxx:1667
const SmMathSymbolNode * ClosingBrace() const
Returns the node containing the data of the closing brace.
Definition: node.hxx:1674
Body of an SmBraceNode.
Definition: node.hxx:1710
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1358
tools::Long mnBodyHeight
Definition: node.hxx:1711
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2367
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2435
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
Definition: node.cxx:2291
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:2301
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2443
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:659
void SetSize(const Size &rSize)
Definition: utility.cxx:199
tools::Long GetBorderWidth() const
Definition: utility.cxx:218
void FreezeBorderWidth()
Definition: utility.hxx:69
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1655
FontSizeType meSizeType
Definition: node.hxx:1933
Fraction maFontSize
Definition: node.hxx:1934
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2383
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
Definition: node.cxx:1631
const Size & GetBaseSize() const
Definition: format.hxx:107
const SmFace & GetFont(sal_uInt16 nIdent) const
Definition: format.hxx:110
sal_uInt16 GetRelSize(sal_uInt16 nIdent) const
Definition: format.hxx:117
bool IsTextmode() const
Definition: format.hxx:126
bool IsScaleNormalBrackets() const
Definition: format.hxx:132
sal_uInt16 GetDistance(sal_uInt16 nIdent) const
Definition: format.hxx:120
sal_Int16 GetGreekCharStyle() const
Definition: format.hxx:129
SmHorAlign GetHorAlign() const
Definition: format.hxx:123
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2423
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:2253
virtual void GetAccessibleText(OUStringBuffer &rText) const override
Appends to rText the node text.
Definition: node.cxx:508
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:600
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2439
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
Definition: node.cxx:586
bool IsUseExtraSpaces() const
Checks if it is using extra spaces.
Definition: node.hxx:1206
virtual void AdaptToY(OutputDevice &rDev, sal_uLong nHeight) override
Definition: node.cxx:2070
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
Definition: node.cxx:2108
SmMathSymbolNode(SmNodeType eNodeType, const SmToken &rNodeToken)
Definition: node.hxx:957
virtual void AdaptToX(OutputDevice &rDev, sal_uLong nWidth) override
Definition: node.cxx:2047
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:2124
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2427
sal_uInt16 mnNumRows
Definition: node.hxx:2001
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1934
virtual const SmNode * GetLeftMost() const override
(this assumes the one with index 0 is always the leftmost subnode for the current node).
Definition: node.cxx:2032
sal_uInt16 mnNumCols
Definition: node.hxx:2002
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2407
SmSymbolManager & GetSymbolManager()
Definition: smmod.cxx:169
Definition: node.hxx:125
virtual void AdaptToY(OutputDevice &rDev, sal_uLong nHeight)
Definition: node.cxx:246
FontAttribute mnAttributes
Definition: node.hxx:136
FontAttribute & Attributes()
Gets the font attributes.
Definition: node.hxx:185
sal_Int32 GetAccessibleIndex() const
Gets the node accessible index.
Definition: node.hxx:326
void SetAttribute(FontAttribute nAttrib)
Sets the font attribute nAttrib.
Definition: node.cxx:97
bool mbIsPhantom
Definition: node.hxx:137
void SetSize(const Fraction &rScale)
Sets the font size to rRelSize with type FontSizeType::ABSOLUT.
Definition: node.cxx:183
void Move(const Point &rVector)
Moves the rectangle by rVector.
Definition: node.cxx:231
SmNode(SmNodeType eNodeType, SmToken aNodeToken)
Definition: node.cxx:48
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat)=0
Prepares the SmRect to render.
virtual ~SmNode()
Definition: node.cxx:62
SmScaleMode GetScaleMode() const
Gets the scale mode.
Definition: node.hxx:362
virtual bool IsVisible() const =0
Checks node visibility.
void SetFont(const SmFace &rFace)
Sets the font to rFace.
Definition: node.cxx:125
RectHorAlign GetRectHorAlign() const
Gets the alignment of the text.
Definition: node.hxx:284
void SetFontSize(const Fraction &rRelSize, FontSizeType nType)
Sets the font size to rRelSize with type nType.
Definition: node.cxx:133
FontChangeMask mnFlags
Definition: node.hxx:135
const SmNode * FindRectClosestTo(const Point &rPoint) const
Finds the closest rectangle in the screen.
Definition: node.cxx:280
const SmRect & GetRect() const
Parses itself to SmRect.
Definition: node.hxx:290
void SetAccessibleIndex(sal_Int32 nAccIndex)
Sets the node accessible index to nAccIndex.
Definition: node.hxx:334
void PrepareAttributes()
Prepare preliminary font attributes Called on Prepare(...).
Definition: node.cxx:200
virtual size_t GetNumSubNodes() const =0
Gets the number of subnodes.
RectHorAlign meRectHorAlign
Definition: node.hxx:134
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
Prepare preliminary settings about font and text (e.g.
Definition: node.cxx:207
void SetPhantom(bool bIsPhantom)
Sets the render visibility of a visible node to bIsPhantom.
Definition: node.cxx:78
const SmToken & GetToken() const
Gets the token.
Definition: node.hxx:387
virtual const SmNode * GetLeftMost() const
(this assumes the one with index 0 is always the leftmost subnode for the current node).
Definition: node.cxx:66
void ClearAttribute(FontAttribute nAttrib)
Clears the font attribute nAttrib.
Definition: node.cxx:111
void SetParent(SmStructureNode *parent)
Sets the parent node.
Definition: node.hxx:451
void MoveTo(const Point &rPoint)
Moves the rectangle to rPoint, being the top left corner the origin.
Definition: node.hxx:304
const SmNode * FindTokenAt(sal_uInt16 nRow, sal_uInt16 nCol) const
Finds the node from the position in the text.
Definition: node.cxx:251
virtual void GetAccessibleText(OUStringBuffer &rText) const =0
Appends to rText the node text.
virtual SmNode * GetSubNode(size_t nIndex)=0
Gets the subnode of index nIndex.
const SmNode * FindNodeWithAccessibleIndex(sal_Int32 nAccIndex) const
Finds the node with accessible index nAccIndex.
Definition: node.cxx:322
void SetRectHorAlign(RectHorAlign eHorAlign, bool bApplyToSubTree=true)
Sets the alignment of the text.
Definition: node.cxx:191
virtual void AdaptToX(OutputDevice &rDev, sal_uLong nWidth)
Definition: node.cxx:241
void SetColor(const Color &rColor)
Sets the font color.
Definition: node.cxx:88
SmNodeType GetType() const
Gets the node type.
Definition: node.hxx:379
FontChangeMask & Flags()
Gets the FontChangeMask flags.
Definition: node.hxx:179
const SmFace & GetFont() const
Gets the font.
Definition: node.hxx:227
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2371
tools::Long CalcSymbolHeight(const SmNode &rSymbol, const SmFormat &rFormat) const
Returns the height of the node in base to the symbol ( rSymbol contains the operator data ) and the f...
Definition: node.cxx:1496
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1524
const SmNode * GetSymbol() const
Returns the node with the operator data.
Definition: node.hxx:1820
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2411
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:2277
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
Definition: node.cxx:2268
Polygon line node.
Definition: node.hxx:700
tools::Long mnWidth
Definition: node.hxx:703
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1723
tools::Polygon maPoly
Definition: node.hxx:701
Size maToSize
Definition: node.hxx:702
tools::Long GetWidth() const
Gets the width of the rect.
Definition: node.hxx:712
SmPolyLineNode(const SmToken &rNodeToken)
Definition: node.cxx:1702
virtual void AdaptToY(OutputDevice &rDev, sal_uLong nHeight) override
Definition: node.cxx:1716
virtual void AdaptToX(OutputDevice &rDev, sal_uLong nWidth) override
Definition: node.cxx:1710
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2447
Definition: rect.hxx:84
tools::Long GetItalicLeft() const
Definition: rect.hxx:140
const Point & GetTopLeft() const
Definition: rect.hxx:124
tools::Long GetItalicWidth() const
Definition: rect.hxx:143
bool IsInsideRect(const Point &rPoint) const
Definition: rect.cxx:596
SmRect()
Definition: rect.cxx:144
tools::Long GetItalicRight() const
Definition: rect.hxx:142
SmRect AsGlyphRect() const
Definition: rect.cxx:613
tools::Long GetAlignT() const
Definition: rect.hxx:149
tools::Long GetHeight() const
Definition: rect.hxx:132
tools::Long OrientedDist(const Point &rPoint) const
Definition: rect.cxx:552
tools::Long GetItalicCenterX() const
Definition: rect.hxx:141
bool HasBaseline() const
Definition: rect.hxx:145
void Move(const Point &rPosition)
Definition: rect.cxx:317
tools::Long GetTop() const
Definition: rect.hxx:126
tools::Long GetBottom() const
Definition: rect.hxx:128
sal_uInt16 GetBorderWidth() const
Definition: rect.hxx:113
SmRect & ExtendBy(const SmRect &rRect, RectCopyMBL eCopyMode)
Definition: rect.cxx:461
tools::Long GetBaseline() const
Definition: rect.hxx:204
Point AlignTo(const SmRect &rRect, RectPos ePos, RectHorAlign eHor, RectVerAlign eVer) const
Definition: rect.cxx:334
tools::Long GetAlignB() const
Definition: rect.hxx:151
tools::Long GetWidth() const
Definition: rect.hxx:131
tools::Long GetAlignM() const
Definition: rect.hxx:150
void SetItalicSpaces(tools::Long nLeftSpace, tools::Long nRightSpace)
Definition: rect.hxx:186
void MoveTo(const Point &rPosition)
Definition: rect.hxx:159
tools::Long GetLeft() const
Definition: rect.hxx:127
void SetWidth(sal_uLong nWidth)
Definition: rect.hxx:117
const Size & GetSize() const
Definition: rect.hxx:153
tools::Long GetItalicRightSpace() const
Definition: rect.hxx:135
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2459
virtual void AdaptToX(OutputDevice &rDev, sal_uLong nWidth) override
Definition: node.cxx:1781
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1794
Size maToSize
Definition: node.hxx:666
virtual void AdaptToY(OutputDevice &rDev, sal_uLong nHeight) override
Definition: node.cxx:1787
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:740
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2451
sal_uLong mnBodyWidth
Definition: node.hxx:1021
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2455
virtual void AdaptToX(OutputDevice &rDev, sal_uLong nHeight) override
Definition: node.cxx:1764
virtual void AdaptToY(OutputDevice &rDev, sal_uLong nHeight) override
Definition: node.cxx:1770
Special node for user defined characters.
Definition: node.hxx:878
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2419
SmSpecialNode(SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 _nFontDesc)
Definition: node.cxx:2162
bool mbIsFromGreekSymbolSet
Definition: node.hxx:879
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:2240
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
Definition: node.cxx:2176
Abstract baseclass for all composite node.
Definition: node.hxx:471
virtual ~SmStructureNode() override
Definition: node.cxx:353
void SetSubNodesBinMo(std::unique_ptr< SmNode > pFirst, std::unique_ptr< SmNode > pSecond, std::unique_ptr< SmNode > pThird=nullptr)
Sets subnodes, used for operators.
Definition: node.cxx:392
int IndexOfSubNode(SmNode const *pSubNode)
Get the index of the child node pSubNode.
Definition: node.cxx:468
void ClaimPaternity()
Sets parent on children of this node.
Definition: node.cxx:463
SmNode * GetSubNodeBinMo(size_t nIndex) const
Gets the subnode of index nIndex, used for operators.
Definition: node.cxx:440
virtual size_t GetNumSubNodes() const override
Gets the number of subnodes.
Definition: node.cxx:430
SmNodeArray maSubNodes
Definition: node.hxx:472
virtual void GetAccessibleText(OUStringBuffer &rText) const override
Appends to rText the node text.
Definition: node.cxx:452
void SetSubNodes(std::unique_ptr< SmNode > pFirst, std::unique_ptr< SmNode > pSecond, std::unique_ptr< SmNode > pThird=nullptr)
Sets subnodes, used for operators.
Definition: node.cxx:364
virtual SmNode * GetSubNode(size_t nIndex) override
Gets the subnode of index nIndex.
Definition: node.cxx:435
void SetSubNode(size_t nIndex, SmNode *pNode)
Sets the subnode pNode at nIndex.
Definition: node.cxx:477
void ClearSubNodes()
Does the cleaning of the subnodes.
Definition: node.cxx:359
virtual bool IsVisible() const override
Checks node visibility.
Definition: node.cxx:425
Super- and subscript node.
Definition: node.hxx:1559
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2403
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1152
const SmNode * GetBody() const
Returns the node with the data of what has to be superindex or subindex.
Definition: node.hxx:1571
const SmNode * GetSubSup(SmSubSup eSubSup) const
Gets the node with the data of what has to be superindex or subindex.
Definition: node.hxx:1595
Definition: symbol.hxx:37
const OUString & GetSymbolSetName() const
Definition: symbol.hxx:59
sal_UCS4 GetCharacter() const
Definition: symbol.hxx:55
const vcl::Font & GetFace() const
Definition: symbol.hxx:54
SmSym * GetSymbolByName(const OUString &rSymbolName)
Definition: symbol.cxx:112
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:513
virtual const SmNode * GetLeftMost() const override
(this assumes the one with index 0 is always the leftmost subnode for the current node).
Definition: node.cxx:571
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2359
tools::Long mnFormulaBaseline
Definition: node.hxx:1140
tools::Long GetFormulaBaseline() const
Gets the formula baseline.
Definition: node.cxx:577
Text node.
Definition: node.hxx:747
void ChangeText(const OUString &rText)
Change the text of this node, including the underlying token to rText.
Definition: node.cxx:1836
OUString maText
Definition: node.hxx:748
void AdjustFontDesc()
Try to guess the correct FontDesc, used during visual editing.
Definition: node.cxx:1887
void SetText(const OUString &rText)
Sets the node text to rText.
Definition: node.hxx:776
static sal_Unicode ConvertSymbolToUnicode(sal_Unicode nIn)
Converts the character from StarMath's private area symbols to a matching Unicode character,...
Definition: node.cxx:1899
const OUString & GetText() const
Gets the node text.
Definition: node.hxx:782
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1868
virtual void GetAccessibleText(OUStringBuffer &rText) const override
Appends to rText the node text.
Definition: node.cxx:1882
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2415
SmTextNode(SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 nFontDescP)
Definition: node.cxx:1820
sal_uInt16 GetFontDesc() const
Returns the font type being used (text, variable, symbol, ...).
Definition: node.hxx:769
sal_uInt16 mnFontDesc
Definition: node.hxx:749
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth) override
Prepare preliminary settings about font and text (e.g.
Definition: node.cxx:1842
void SetFont(const vcl::Font &rNewFont)
Definition: tmpdevice.cxx:62
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2387
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:674
virtual void Arrange(OutputDevice &rDev, const SmFormat &rFormat) override
Prepares the SmRect to render.
Definition: node.cxx:1422
void Accept(SmVisitor *pVisitor) override
Accept a visitor.
Definition: node.cxx:2463
const SmMathSymbolNode * Brace() const
Returns the node containing the data of the brace.
Definition: node.hxx:1767
const SmNode * Script() const
Returns the node containing the data of what is in the brace.
Definition: node.hxx:1780
const SmNode * Body() const
Returns the node containing the data of what the brace is pointing for.
Definition: node.hxx:1760
Abstract base class for all visible node.
Definition: node.hxx:613
virtual SmNode * GetSubNode(size_t nIndex) override
Gets the subnode of index nIndex.
Definition: node.cxx:503
virtual size_t GetNumSubNodes() const override
Gets the number of subnodes.
Definition: node.cxx:498
virtual bool IsVisible() const override
Checks node visibility.
Definition: node.cxx:493
Visitors are an easy way to automating operations with nodes.
Definition: visitors.hxx:35
virtual void Visit(SmTableNode *pNode)=0
void SetPoint(const Point &rPt, sal_uInt16 nPos)
sal_uInt16 GetSize() const
void SetColor(const Color &)
void SetItalic(FontItalic)
void SetWeight(FontWeight)
const Size & GetFontSize() const
constexpr ::Color COL_GRAY(0x80, 0x80, 0x80)
constexpr ::Color COL_RED(0x80, 0x00, 0x00)
ColorTransparency
float u
DocumentType eType
ITALIC_NORMAL
ITALIC_NONE
WEIGHT_BOLD
WEIGHT_NORMAL
#define FNT_SERIF
Definition: format.hxx:50
#define DIS_NUMERATOR
Definition: format.hxx:63
#define DIS_HORIZONTAL
Definition: format.hxx:58
#define DIS_SUPERSCRIPT
Definition: format.hxx:61
#define DIS_BRACKETSIZE
Definition: format.hxx:69
#define DIS_BRACKETSPACE
Definition: format.hxx:70
#define FNT_FIXED
Definition: format.hxx:52
#define DIS_MATRIXCOL
Definition: format.hxx:72
#define DIS_SUBSCRIPT
Definition: format.hxx:62
#define DIS_OPERATORSIZE
Definition: format.hxx:75
#define SIZ_OPERATOR
Definition: format.hxx:40
#define SIZ_FUNCTION
Definition: format.hxx:39
#define SIZ_INDEX
Definition: format.hxx:38
#define DIS_NORMALBRACKETSIZE
Definition: format.hxx:81
#define FNT_MATH
Definition: format.hxx:53
#define DIS_LOWERLIMIT
Definition: format.hxx:68
#define DIS_OPERATORSPACE
Definition: format.hxx:76
#define DIS_STROKEWIDTH
Definition: format.hxx:66
#define DIS_DENOMINATOR
Definition: format.hxx:64
#define DIS_UPPERLIMIT
Definition: format.hxx:67
#define FNT_FUNCTION
Definition: format.hxx:47
#define FNT_NUMBER
Definition: format.hxx:48
#define DIS_FRACTION
Definition: format.hxx:65
#define FNT_TEXT
Definition: format.hxx:49
#define DIS_VERTICAL
Definition: format.hxx:59
#define DIS_ORNAMENTSPACE
Definition: format.hxx:74
#define SIZ_TEXT
Definition: format.hxx:37
#define SIZ_LIMITS
Definition: format.hxx:41
#define DIS_MATRIXROW
Definition: format.hxx:71
#define DIS_ORNAMENTSIZE
Definition: format.hxx:73
#define FNT_SANS
Definition: format.hxx:51
#define DIS_ROOT
Definition: format.hxx:60
#define FNT_VARIABLE
Definition: format.hxx:46
FuncFlags mnFlags
sal_Int32 nIndex
OUString aName
const long LONG_MAX
#define SAL_WARN(area, stream)
OUString GetExportSymbolSetName(std::u16string_view rUiName)
Definition: smmod.cxx:96
sal_uInt16 GetFontSize(sal_uInt16 nPos)
double getLength(const B2DPolygon &rCandidate)
constexpr double deg2rad(double v)
size
int i
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
None
long Long
vcl::Font GetFont(vcl::Font const &rFont, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
static bool lcl_IsFromGreekSymbolSet(std::u16string_view aTokenText)
Definition: node.cxx:2145
FontChangeMask
Definition: node.hxx:94
FontSizeType
Definition: node.hxx:85
std::vector< SmNode * > SmNodeArray
Definition: node.hxx:113
SmSubSup
Enum used to index sub-/supscripts in the 'maSubNodes' array in 'SmSubSupNode'.
Definition: node.hxx:1536
@ LSUB
Definition: node.hxx:1536
@ CSUB
Definition: node.hxx:1536
@ RSUP
Definition: node.hxx:1536
@ RSUB
Definition: node.hxx:1536
@ LSUP
Definition: node.hxx:1536
@ CSUP
Definition: node.hxx:1536
#define SUBSUP_NUM_ENTRIES
numbers of entries in the above enum (that is: the number of possible sub-/supscripts)
Definition: node.hxx:1542
FontAttribute
The SmNode is the basic structure of formula data.
Definition: node.hxx:73
SmScaleMode
Definition: node.hxx:118
SmNodeType
This file provides definition for the nodetypes.
Definition: nodetype.hxx:26
QPRO_FUNC_TYPE nType
RectHorAlign
Definition: rect.hxx:54
RectVerAlign
Definition: rect.hxx:61
RectPos
Definition: rect.hxx:45
tools::Long SmFromTo(tools::Long nFrom, tools::Long nTo, double fRelDist)
Definition: rect.hxx:30
double mnWidth
#define SM_MOD()
Definition: smmod.hxx:98
sal_uIntPtr sal_uLong
SmTokenType eType
Definition: token.hxx:213
OUString cMathChar
Definition: token.hxx:214
OUString aText
Definition: token.hxx:212
@ Limit
@ Function
SmTokenType
Definition: token.hxx:71
@ TSIZE
Definition: token.hxx:115
@ TNITALIC
Definition: token.hxx:116
@ TUNDERLINE
Definition: token.hxx:118
@ TLIMINF
Definition: token.hxx:86
@ TMATHMLCOL
Definition: token.hxx:147
@ TALIGNL
Definition: token.hxx:117
@ TRGBA
Definition: token.hxx:146
@ TUNKNOWN
Definition: token.hxx:74
@ TALIGNR
Definition: token.hxx:117
@ TSERIF
Definition: token.hxx:119
@ TSPECIAL
Definition: token.hxx:74
@ TNBOLD
Definition: token.hxx:116
@ TICONICCOL
Definition: token.hxx:147
@ TLIMSUP
Definition: token.hxx:86
@ TABS
Definition: token.hxx:144
@ TSANS
Definition: token.hxx:119
@ TRGB
Definition: token.hxx:146
@ TBOLD
Definition: token.hxx:116
@ TWIDESLASH
Definition: token.hxx:88
@ TLIM
Definition: token.hxx:86
@ THTMLCOL
Definition: token.hxx:146
@ TFACT
Definition: token.hxx:144
@ TALIGNC
Definition: token.hxx:117
@ TSBLANK
Definition: token.hxx:75
@ TBLANK
Definition: token.hxx:75
@ TDVIPSNAMESCOL
Definition: token.hxx:146
@ TFIXED
Definition: token.hxx:119
@ TWIDEBACKSLASH
Definition: token.hxx:88
@ TITALIC
Definition: token.hxx:116
@ TTEXT
Definition: token.hxx:124
@ TINTD
Definition: token.hxx:135
@ TOVERBRACE
Definition: token.hxx:126
@ THEX
Definition: token.hxx:146
@ TPHANTOM
Definition: token.hxx:115
@ TOVERSTRIKE
Definition: token.hxx:118
Left
sal_uInt16 sal_Unicode
sal_Unicode const MS_DVERTLINE
Definition: types.hxx:111
sal_Unicode const MS_DLINE
Definition: types.hxx:110
sal_Unicode const MS_LINE
Definition: types.hxx:108
sal_Unicode const MS_VERTLINE
Definition: types.hxx:109
void GetSelection(struct ESelection &rSel, SvxTextForwarder const *pForwarder) noexcept
bool IsItalic(const vcl::Font &rFont)
Definition: utility.cxx:176
bool IsBold(const vcl::Font &rFont)
Definition: utility.cxx:184
o3tl::Length SmO3tlLengthUnit()
Definition: utility.hxx:125
sal_uInt32 sal_UCS4
RedlineType meType