LibreOffice Module starmath (master) 1
visitors.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
10#include <rtl/math.hxx>
11#include <sal/log.hxx>
12#include <tools/gen.hxx>
13#include <vcl/lineinfo.hxx>
14#include <visitors.hxx>
15#include "tmpdevice.hxx"
16#include <cursor.hxx>
17
18#include <starmathdatabase.hxx>
19
20// SmDefaultingVisitor
21
23{
24 DefaultVisit( pNode );
25}
26
28{
29 DefaultVisit( pNode );
30}
31
33{
34 DefaultVisit( pNode );
35}
36
38{
39 DefaultVisit( pNode );
40}
41
43{
44 DefaultVisit( pNode );
45}
46
48{
49 DefaultVisit( pNode );
50}
51
53{
54 DefaultVisit( pNode );
55}
56
58{
59 DefaultVisit( pNode );
60}
61
63{
64 DefaultVisit( pNode );
65}
66
68{
69 DefaultVisit( pNode );
70}
71
73{
74 DefaultVisit( pNode );
75}
76
78{
79 DefaultVisit( pNode );
84 DefaultVisit( pNode );
89 DefaultVisit( pNode );
94 DefaultVisit( pNode );
99 DefaultVisit( pNode );
104 DefaultVisit( pNode );
108{
109 DefaultVisit( pNode );
110}
111
113{
114 DefaultVisit( pNode );
115}
116
118{
119 DefaultVisit( pNode );
120}
121
123{
124 DefaultVisit( pNode );
125}
126
128{
129 DefaultVisit( pNode );
130}
131
133{
134 DefaultVisit( pNode );
135}
136
138{
139 DefaultVisit( pNode );
140}
141
143{
144 DefaultVisit( pNode );
145}
146
148{
149 DefaultVisit( pNode );
150}
151
153{
154 DefaultVisit( pNode );
155}
156
157// SmCaretLinesVisitor
158
160 : mrDev(rDevice)
161 , maPos(position)
162 , maOffset(offset)
163{
164}
165
167{
168 SAL_WARN_IF(!maPos.IsValid(), "starmath", "Cannot draw invalid position!");
169 if (!maPos.IsValid())
170 return;
171
172 //Save device state
174
175 maPos.pSelectedNode->Accept( this );
176 //Restore device state
177 mrDev.Pop( );
178}
179
181{
183
184 mrDev.SetFont( pNode->GetFont( ) );
185
186 //Find the line
187 SmNode* pLine = SmCursor::FindTopMostNodeInLine( pNode );
188
189 //Find coordinates
190 tools::Long left = pNode->GetLeft( ) + mrDev.GetTextWidth( pNode->GetText( ), 0, i ) + maOffset.X( );
191 tools::Long top = pLine->GetTop( ) + maOffset.Y( );
192 tools::Long height = pLine->GetHeight( );
193 tools::Long left_line = pLine->GetLeft( ) + maOffset.X( );
194 tools::Long right_line = pLine->GetRight( ) + maOffset.X( );
195
196 // Vertical line
197 ProcessCaretLine({ left, top }, { left, top + height });
198
199 // Underline
200 ProcessUnderline({ left_line, top + height }, { right_line, top + height });
201}
202
204{
205 //Find the line
206 SmNode* pLine = SmCursor::FindTopMostNodeInLine( pNode );
207
208 //Find coordinates
209 tools::Long left = pNode->GetLeft( ) + maOffset.X( ) + ( maPos.nIndex == 1 ? pNode->GetWidth( ) : 0 );
210 tools::Long top = pLine->GetTop( ) + maOffset.Y( );
211 tools::Long height = pLine->GetHeight( );
212 tools::Long left_line = pLine->GetLeft( ) + maOffset.X( );
213 tools::Long right_line = pLine->GetRight( ) + maOffset.X( );
214
215 // Vertical line
216 ProcessCaretLine({ left, top }, { left, top + height });
217
218 // Underline
219 ProcessUnderline({ left_line, top + height }, { right_line, top + height });
220}
221
222// SmCaretRectanglesVisitor
223
225 : SmCaretLinesVisitor(rDevice, position, {})
226{
227 DoIt();
228}
229
231void SmCaretRectanglesVisitor::ProcessUnderline(Point /*from*/, Point /*to*/) {} // No underline
232
233// SmCaretDrawingVisitor
234
236 SmCaretPos position,
237 Point offset,
238 bool caretVisible )
239 : SmCaretLinesVisitor(rDevice, position, offset)
240 , mbCaretVisible( caretVisible )
241{
242 DoIt();
243}
244
246{
247 if ( mbCaretVisible ) {
248 //Set color
250 //Draw vertical line
252 }
253}
254
256{
257 //Set color
259 //Underline the line
261}
262
263// SmCaretPos2LineVisitor
264
266{
267 //Save device state
269
271
272 mpDev->SetFont( pNode->GetFont( ) );
273
274 //Find coordinates
275 tools::Long left = pNode->GetLeft( ) + mpDev->GetTextWidth( pNode->GetText( ), 0, i );
276 tools::Long top = pNode->GetTop( );
277 tools::Long height = pNode->GetHeight( );
278
279 maLine = SmCaretLine( left, top, height );
280
281 //Restore device state
282 mpDev->Pop( );
283}
284
286{
287 //Vertical line ( code from SmCaretDrawingVisitor )
288 Point p1 = pNode->GetTopLeft( );
289 if( maPos.nIndex == 1 )
290 p1.Move( pNode->GetWidth( ), 0 );
291
292 maLine = SmCaretLine( p1.X( ), p1.Y( ), pNode->GetHeight( ) );
293}
294
295
296// SmDrawingVisitor
297
299{
300 DrawChildren( pNode );
301}
302
304{
305 DrawChildren( pNode );
306}
307
309{
310 DrawChildren( pNode );
311}
312
314{
315 DrawChildren( pNode );
316}
317
319{
320 DrawChildren( pNode );
321}
322
324{
325 DrawChildren( pNode );
326}
327
329{
330 DrawChildren( pNode );
331}
332
334{
335 DrawChildren( pNode );
336}
337
339{
340 DrawChildren( pNode );
341}
342
344{
345 DrawChildren( pNode );
346}
347
349{
350 DrawChildren( pNode );
351}
352
354{
355 DrawChildren( pNode );
356}
357
359{
360 DrawChildren( pNode );
361}
362
364{
365 DrawSpecialNode( pNode );
366}
367
369{
370 DrawTextNode( pNode );
371}
372
374{
375 DrawSpecialNode( pNode );
376}
377
379{
380 DrawSpecialNode( pNode );
381}
382
384{
385 DrawSpecialNode( pNode );
386}
387
389{
390}
391
393{
394 DrawSpecialNode( pNode );
395}
396
398{
399 DrawChildren( pNode );
400}
401
403{
404 DrawChildren( pNode );
405}
406
408{
409 DrawChildren( pNode );
410}
411
413{
414 DrawChildren( pNode );
415}
416
418{
419 if ( pNode->IsPhantom( ) )
420 return;
421
422 // draw root-sign itself
423 DrawSpecialNode( pNode );
424
425 SmTmpDevice aTmpDev( mrDev, true );
426 aTmpDev.SetFillColor( pNode->GetFont( ).GetColor( ) );
428 aTmpDev.SetFont( pNode->GetFont( ) );
429
430 // since the width is always unscaled it corresponds to the _original_
431 // _unscaled_ font height to be used, we use that to calculate the
432 // bar height. Thus it is independent of the arguments height.
433 // ( see display of sqrt QQQ versus sqrt stack{Q#Q#Q#Q} )
434 tools::Long nBarHeight = pNode->GetWidth( ) * 7 / 100;
435 tools::Long nBarWidth = pNode->GetBodyWidth( ) + pNode->GetBorderWidth( );
436 Point aBarOffset( pNode->GetWidth( ), +pNode->GetBorderWidth( ) );
437 Point aBarPos( maPosition + aBarOffset );
438
439 tools::Rectangle aBar( aBarPos, Size( nBarWidth, nBarHeight ) );
442 // This is done by shifting its output-position to a point that
443 // corresponds exactly to a pixel on the output device.
444 Point aDrawPos( mrDev.PixelToLogic( mrDev.LogicToPixel( aBar.TopLeft( ) ) ) );
445 aBar.SetPos( aDrawPos );
446
447 mrDev.DrawRect( aBar );
448}
449
451{
452 if ( pNode->IsPhantom( ) )
453 return;
454
455 tools::Long nBorderwidth = pNode->GetFont( ).GetBorderWidth( );
456
457 LineInfo aInfo;
458 aInfo.SetWidth( pNode->GetWidth( ) - 2 * nBorderwidth );
459
460 Point aOffset ( Point( ) - pNode->GetPolygon( ).GetBoundRect( ).TopLeft( )
461 + Point( nBorderwidth, nBorderwidth ) ),
462 aPos ( maPosition + aOffset );
463 pNode->GetPolygon( ).Move( aPos.X( ), aPos.Y( ) ); //Works because Polygon wraps a pointer
464
465 SmTmpDevice aTmpDev ( mrDev, false );
466 aTmpDev.SetLineColor( pNode->GetFont( ).GetColor( ) );
467
468 mrDev.DrawPolyLine( pNode->GetPolygon( ), aInfo );
469}
470
472{
473 if ( pNode->IsPhantom( ) )
474 return;
475
476 SmTmpDevice aTmpDev ( mrDev, false );
477 aTmpDev.SetFillColor( pNode->GetFont( ).GetColor( ) );
479 aTmpDev.SetFont( pNode->GetFont( ) );
480
481 sal_uLong nTmpBorderWidth = pNode->GetFont( ).GetBorderWidth( );
482
483 // get rectangle and remove borderspace
484 tools::Rectangle aTmp ( pNode->AsRectangle( ) + maPosition - pNode->GetTopLeft( ) );
485 aTmp.AdjustLeft(nTmpBorderWidth );
486 aTmp.AdjustRight( -sal_Int32(nTmpBorderWidth) );
487 aTmp.AdjustTop(nTmpBorderWidth );
488 aTmp.AdjustBottom( -sal_Int32(nTmpBorderWidth) );
489
490 SAL_WARN_IF( aTmp.IsEmpty(), "starmath", "Empty rectangle" );
491
494 // This is done by shifting its output-position to a point that
495 // corresponds exactly to a pixel on the output device.
496 Point aPos ( mrDev.PixelToLogic( mrDev.LogicToPixel( aTmp.TopLeft( ) ) ) );
497 aTmp.SetPos( aPos );
498
499 mrDev.DrawRect( aTmp );
500}
501
503{
504 if ( pNode->IsPhantom() || pNode->GetText().isEmpty() || pNode->GetText()[0] == '\0' )
505 return;
506
507 SmTmpDevice aTmpDev ( mrDev, false );
508 aTmpDev.SetFont( pNode->GetFont( ) );
509
510 Point aPos ( maPosition );
511 aPos.AdjustY(pNode->GetBaselineOffset( ) );
512 // round to pixel coordinate
513 aPos = mrDev.PixelToLogic( mrDev.LogicToPixel( aPos ) );
514
515 mrDev.DrawStretchText( aPos, pNode->GetWidth( ), pNode->GetText( ) );
516}
517
519{
523
524 DrawTextNode( pNode );
525}
526
528{
529 if ( pNode->IsPhantom( ) )
530 return;
531
532 Point rPosition = maPosition;
533
534 for( auto pChild : *pNode )
535 {
536 if(!pChild)
537 continue;
538 Point aOffset ( pChild->GetTopLeft( ) - pNode->GetTopLeft( ) );
539 maPosition = rPosition + aOffset;
540 pChild->Accept( this );
541 }
542}
543
544// SmSetSelectionVisitor
545
547 : maStartPos(startPos)
548 , maEndPos(endPos)
549 , mbSelecting(false)
550{
551 //Assume that pTree is a SmTableNode
552 SAL_WARN_IF(pTree->GetType() != SmNodeType::Table, "starmath", "pTree should be a SmTableNode!");
553 //Visit root node, this is special as this node cannot be selected, but its children can!
554 if(pTree->GetType() == SmNodeType::Table){
555 //Change state if maStartPos is in front of this node
556 if( maStartPos.pSelectedNode == pTree && maStartPos.nIndex == 0 )
558 //Change state if maEndPos is in front of this node
559 if( maEndPos.pSelectedNode == pTree && maEndPos.nIndex == 0 )
561 SAL_WARN_IF(mbSelecting, "starmath", "Caret positions needed to set mbSelecting about, shouldn't be possible!");
562
563 //Visit lines
564 for( auto pChild : *static_cast<SmStructureNode*>(pTree) )
565 {
566 if(!pChild)
567 continue;
568 pChild->Accept( this );
569 //If we started a selection in this line and it haven't ended, we do that now!
570 if(mbSelecting) {
571 mbSelecting = false;
572 SetSelectedOnAll(pChild);
573 //Set maStartPos and maEndPos to invalid positions, this ensures that an unused
574 //start or end (because we forced end above), doesn't start a new selection.
576 }
577 }
578 //Check if pTree isn't selected
579 SAL_WARN_IF(pTree->IsSelected(), "starmath", "pTree should never be selected!");
580 //Discard the selection if there's a bug (it's better than crashing)
581 if(pTree->IsSelected())
582 SetSelectedOnAll(pTree, false);
583 }else //This shouldn't happen, but I don't see any reason to die if it does
584 pTree->Accept(this);
585}
586
587void SmSetSelectionVisitor::SetSelectedOnAll( SmNode* pSubTree, bool IsSelected ) {
588 pSubTree->SetSelected( IsSelected );
589
590 if(pSubTree->GetNumSubNodes() == 0)
591 return;
592 //Quick BFS to set all selections
593 for( auto pChild : *static_cast<SmStructureNode*>(pSubTree) )
594 {
595 if(!pChild)
596 continue;
597 SetSelectedOnAll( pChild, IsSelected );
598 }
599}
600
602 //Change state if maStartPos is in front of this node
603 if( maStartPos.pSelectedNode == pNode && maStartPos.nIndex == 0 )
605 //Change state if maEndPos is in front of this node
606 if( maEndPos.pSelectedNode == pNode && maEndPos.nIndex == 0 )
608
609 //Cache current state
610 bool WasSelecting = mbSelecting;
611 bool ChangedState = false;
612
613 //Set selected
614 pNode->SetSelected( mbSelecting );
615
616 //Visit children
617 if(pNode->GetNumSubNodes() > 0)
618 {
619 for( auto pChild : *static_cast<SmStructureNode*>(pNode) )
620 {
621 if(!pChild)
622 continue;
623 pChild->Accept( this );
624 ChangedState = ( WasSelecting != mbSelecting ) || ChangedState;
625 }
626 }
627
628 //If state changed
629 if( ChangedState )
630 {
631 //Select this node and all of its children
632 //(Make exception for SmBracebodyNode)
633 if( pNode->GetType() != SmNodeType::Bracebody ||
634 !pNode->GetParent() ||
635 pNode->GetParent()->GetType() != SmNodeType::Brace )
636 SetSelectedOnAll( pNode );
637 else
638 SetSelectedOnAll( pNode->GetParent() );
639 /* If the equation is: sqrt{2 + 4} + 5
640 * And the selection is: sqrt{2 + [4} +] 5
641 * Where [ denotes maStartPos and ] denotes maEndPos
642 * Then the sqrt node should be selected, so that the
643 * effective selection is: [sqrt{2 + 4} +] 5
644 * The same is the case if we swap maStartPos and maEndPos.
645 */
646 }
647
648 //Change state if maStartPos is after this node
649 if( maStartPos.pSelectedNode == pNode && maStartPos.nIndex == 1 )
650 {
652 }
653 //Change state if maEndPos is after of this node
654 if( maEndPos.pSelectedNode == pNode && maEndPos.nIndex == 1 )
655 {
657 }
658}
659
661{
662 //Change state if maStartPos is in front of this node
663 if( maStartPos.pSelectedNode == pNode && maStartPos.nIndex == 0 )
665 //Change state if maEndPos is in front of this node
666 if( maEndPos.pSelectedNode == pNode && maEndPos.nIndex == 0 )
668
669 //Cache current state
670 bool WasSelecting = mbSelecting;
671
672 //Visit children
673 for( auto pChild : *pNode )
674 {
675 if(!pChild)
676 continue;
677 pChild->Accept( this );
678 }
679
680 //Set selected, if everything was selected
681 pNode->SetSelected( WasSelecting && mbSelecting );
682
683 //Change state if maStartPos is after this node
684 if( maStartPos.pSelectedNode == pNode && maStartPos.nIndex == 1 )
686 //Change state if maEndPos is after of this node
687 if( maEndPos.pSelectedNode == pNode && maEndPos.nIndex == 1 )
689}
690
692 tools::Long i1 = -1,
693 i2 = -1;
694 if( maStartPos.pSelectedNode == pNode )
695 i1 = maStartPos.nIndex;
696 if( maEndPos.pSelectedNode == pNode )
697 i2 = maEndPos.nIndex;
698
700 pNode->SetSelected(true);
701 if( i1 != -1 && i2 != -1 ) {
702 start = std::min(i1, i2);
703 end = std::max(i1, i2);
704 } else if( mbSelecting && i1 != -1 ) {
705 start = 0;
706 end = i1;
707 mbSelecting = false;
708 } else if( mbSelecting && i2 != -1 ) {
709 start = 0;
710 end = i2;
711 mbSelecting = false;
712 } else if( !mbSelecting && i1 != -1 ) {
713 start = i1;
714 end = pNode->GetText().getLength();
715 mbSelecting = true;
716 } else if( !mbSelecting && i2 != -1 ) {
717 start = i2;
718 end = pNode->GetText().getLength();
719 mbSelecting = true;
720 } else if( mbSelecting ) {
721 start = 0;
722 end = pNode->GetText().getLength();
723 } else {
724 pNode->SetSelected( false );
725 start = 0;
726 end = 0;
727 }
728 pNode->SetSelected( start != end );
729 pNode->SetSelectionStart( start );
730 pNode->SetSelectionEnd( end );
731}
732
734 VisitCompositionNode( pNode );
735}
736
738 VisitCompositionNode( pNode );
739}
740
742 VisitCompositionNode( pNode );
743}
744
746 VisitCompositionNode( pNode );
747}
748
750 VisitCompositionNode( pNode );
751}
752
754 VisitCompositionNode( pNode );
755}
756
757// SmCaretPosGraphBuildingVisitor
758
760 : mpRightMost(nullptr)
761 , mpGraph(new SmCaretPosGraph)
762{
763 //pRootNode should always be a table
764 SAL_WARN_IF( pRootNode->GetType( ) != SmNodeType::Table, "starmath", "pRootNode must be a table node");
765 //Handle the special case where SmNodeType::Table is used a rootnode
766 if( pRootNode->GetType( ) == SmNodeType::Table ){
767 //Children are SmLineNodes
768 //Or so I thought... Apparently, the children can be instances of SmExpression
769 //especially if there's an error in the formula... So here we go, a simple work around.
770 for( auto pChild : *static_cast<SmStructureNode*>(pRootNode) )
771 {
772 if(!pChild)
773 continue;
774 mpRightMost = mpGraph->Add( SmCaretPos( pChild, 0 ) );
775 pChild->Accept( this );
776 }
777 }else
778 pRootNode->Accept(this);
779}
780
782{
783}
784
786 for( auto pChild : *pNode )
787 {
788 if(!pChild)
789 continue;
790 pChild->Accept( this );
791 }
792}
793
801 *right = mpGraph->Add( SmCaretPos( pNode, 1) );
802 bool bIsFirst = true;
803 for( auto pChild : *pNode )
804 {
805 if(!pChild)
806 continue;
807 mpRightMost = mpGraph->Add( SmCaretPos( pChild, 0 ), left);
808 if(bIsFirst)
809 left->SetRight(mpRightMost);
810 pChild->Accept( this );
812 if(bIsFirst)
813 right->SetLeft(mpRightMost);
814 bIsFirst = false;
815 }
817}
818
850{
852 *right,
853 *bodyLeft,
854 *bodyRight;
855
856 assert(mpRightMost);
858
859 //Create bodyLeft
860 SAL_WARN_IF( !pNode->GetBody(), "starmath", "SmSubSupNode Doesn't have a body!" );
861 bodyLeft = mpGraph->Add( SmCaretPos( pNode->GetBody( ), 0 ), left );
862 left->SetRight( bodyLeft ); //TODO: Don't make this if LSUP or LSUB are NULL ( not sure??? )
863
864 //Create right
865 right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
866
867 //Visit the body, to get bodyRight
868 mpRightMost = bodyLeft;
869 pNode->GetBody( )->Accept( this );
870 bodyRight = mpRightMost;
871 bodyRight->SetRight( right );
872 right->SetLeft( bodyRight );
873
874 SmNode* pChild;
875 for (SmSubSup const nodeType : { LSUP, LSUB, CSUP, CSUB, RSUP, RSUB })
876 {
877 pChild = pNode->GetSubSup(nodeType);
878 if( pChild )
879 {
880 SmCaretPosGraphEntry *cLeft; //Child left
881 cLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), ((nodeType == RSUP) || (nodeType == RSUB))?bodyRight:left );
882
883 mpRightMost = cLeft;
884 pChild->Accept( this );
885
886 mpRightMost->SetRight( ((nodeType == LSUP) || (nodeType == LSUB))?bodyLeft:right );
887 }
888 }
889
890 //Set return parameters
892}
893
932{
933 SmNode *pOper = pNode->GetSubNode( 0 ),
934 *pBody = pNode->GetSubNode( 1 );
935
937 *bodyLeft,
938 *bodyRight,
939 *right;
940 //Create body left
941 bodyLeft = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
942 left->SetRight( bodyLeft );
943
944 //Visit body, get bodyRight
945 mpRightMost = bodyLeft;
946 pBody->Accept( this );
947 bodyRight = mpRightMost;
948
949 //Create right
950 right = mpGraph->Add( SmCaretPos( pNode, 1 ), bodyRight );
951 bodyRight->SetRight( right );
952
953 //Get subsup pNode if any
954 SmSubSupNode* pSubSup = pOper->GetType( ) == SmNodeType::SubSup ? static_cast<SmSubSupNode*>(pOper) : nullptr;
955
956 if( pSubSup ) {
957 SmNode* pChild;
958 for (SmSubSup const nodeType : { LSUP, LSUB, CSUP, CSUB, RSUP, RSUB })
959 {
960 pChild = pSubSup->GetSubSup(nodeType);
961 if( pChild )
962 {
963 //Create position in front of pChild
964 SmCaretPosGraphEntry *childLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
965 //Visit pChild
966 mpRightMost = childLeft;
967 pChild->Accept( this );
968 //Set right on mpRightMost from pChild
969 mpRightMost->SetRight( bodyLeft );
970 }
971 }
972 }
973
974 //Return right
976}
977
979{
981 *right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
982
983 for (size_t i = 0; i < pNode->GetNumRows(); ++i)
984 {
986 for (size_t j = 0; j < pNode->GetNumCols(); ++j)
987 {
988 SmNode* pSubNode = pNode->GetSubNode( i * pNode->GetNumCols( ) + j );
989
990 mpRightMost = mpGraph->Add( SmCaretPos( pSubNode, 0 ), r );
991 if( j != 0 || ( pNode->GetNumRows() - 1U ) / 2 == i )
992 r->SetRight( mpRightMost );
993
994 pSubNode->Accept( this );
995
996 r = mpRightMost;
997 }
999 if( ( pNode->GetNumRows() - 1U ) / 2 == i )
1000 right->SetLeft( mpRightMost );
1001 }
1002
1004}
1005
1025{
1026 SAL_WARN_IF( pNode->GetText().isEmpty(), "starmath", "Empty SmTextNode is bad" );
1027
1028 int size = pNode->GetText().getLength();
1029 for( int i = 1; i <= size; i++ ){
1031 mpRightMost = mpGraph->Add( SmCaretPos( pNode, i ), pRight );
1032 pRight->SetRight( mpRightMost );
1033 }
1034}
1035
1055{
1056 //None if these children can be NULL, see SmBinVerNode::Arrange
1057 SmNode *pNum = pNode->GetSubNode( 0 ),
1058 *pDenom = pNode->GetSubNode( 2 );
1059
1061 *right,
1062 *numLeft,
1063 *denomLeft;
1064
1065 assert(mpRightMost);
1066 //Set left
1067 left = mpRightMost;
1068
1069 //Create right
1070 right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
1071
1072 //Create numLeft
1073 numLeft = mpGraph->Add( SmCaretPos( pNum, 0 ), left );
1074 left->SetRight( numLeft );
1075
1076 //Visit pNum
1077 mpRightMost = numLeft;
1078 pNum->Accept( this );
1080 right->SetLeft( mpRightMost );
1081
1082 //Create denomLeft
1083 denomLeft = mpGraph->Add( SmCaretPos( pDenom, 0 ), left );
1084
1085 //Visit pDenom
1086 mpRightMost = denomLeft;
1087 pDenom->Accept( this );
1089
1090 //Set return parameter
1092}
1093
1106{
1107 SmNode *pBody = pNode->Body(),
1108 *pScript = pNode->Script();
1109 //None of these children can be NULL
1110
1112 *bodyLeft,
1113 *scriptLeft,
1114 *right;
1115
1116 left = mpRightMost;
1117
1118 //Create right
1119 right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
1120
1121 //Create bodyLeft
1122 bodyLeft = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
1123 left->SetRight( bodyLeft );
1124 mpRightMost = bodyLeft;
1125 pBody->Accept( this );
1127 right->SetLeft( mpRightMost );
1128
1129 //Create script
1130 scriptLeft = mpGraph->Add( SmCaretPos( pScript, 0 ), left );
1131 mpRightMost = scriptLeft;
1132 pScript->Accept( this );
1134
1135 //Set return value
1137}
1138
1152{
1153 SmNode *A = pNode->GetSubNode( 0 ),
1154 *B = pNode->GetSubNode( 1 );
1155
1157 *leftA,
1158 *rightA,
1159 *leftB,
1160 *right;
1161 left = mpRightMost;
1162
1163 //Create right
1164 right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
1165
1166 //Create left A
1167 leftA = mpGraph->Add( SmCaretPos( A, 0 ), left );
1168 left->SetRight( leftA );
1169
1170 //Visit A
1171 mpRightMost = leftA;
1172 A->Accept( this );
1173 rightA = mpRightMost;
1174
1175 //Create left B
1176 leftB = mpGraph->Add( SmCaretPos( B, 0 ), rightA );
1177 rightA->SetRight( leftB );
1178
1179 //Visit B
1180 mpRightMost = leftB;
1181 B->Accept( this );
1183 right->SetLeft( mpRightMost );
1184
1185 //Set return value
1187}
1188
1189//Straight forward ( I think )
1191{
1192 for( auto pChild : *pNode )
1193 {
1194 if(!pChild)
1195 continue;
1196 pChild->Accept( this );
1197 }
1198}
1200{
1201 // Unary operator node
1202 for( auto pChild : *pNode )
1203 {
1204 if(!pChild)
1205 continue;
1206 pChild->Accept( this );
1207 }
1208}
1209
1211{
1212 for( auto pChild : *pNode )
1213 {
1214 if(!pChild)
1215 continue;
1216 pChild->Accept( this );
1217 }
1218}
1219
1221{
1222 //Has only got one child, should act as an expression if possible
1223 for( auto pChild : *pNode )
1224 {
1225 if(!pChild)
1226 continue;
1227 pChild->Accept( this );
1228 }
1229}
1230
1272{
1273 for( auto pChild : *pNode )
1274 {
1275 if(!pChild)
1276 continue;
1277 SmCaretPosGraphEntry* pStart = mpGraph->Add( SmCaretPos( pChild, 0), mpRightMost );
1278 mpRightMost->SetRight( pStart );
1279 mpRightMost = pStart;
1280 pChild->Accept( this );
1281 }
1282}
1283
1288{
1289 for( auto pChild : *pNode )
1290 {
1291 if(!pChild)
1292 continue;
1293 pChild->Accept( this );
1294 }
1295}
1296
1319{
1320 SmNode *pExtra = pNode->GetSubNode( 0 ), //Argument, NULL for sqrt, and SmTextNode if cubicroot
1321 *pBody = pNode->GetSubNode( 2 ); //Body of the root
1322 assert(pBody);
1323
1325 *right,
1326 *bodyLeft,
1327 *bodyRight;
1328
1329 //Get left and save it
1330 assert(mpRightMost);
1331 left = mpRightMost;
1332
1333 //Create body left
1334 bodyLeft = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
1335 left->SetRight( bodyLeft );
1336
1337 //Create right
1338 right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
1339
1340 //Visit body
1341 mpRightMost = bodyLeft;
1342 pBody->Accept( this );
1343 bodyRight = mpRightMost;
1344 bodyRight->SetRight( right );
1345 right->SetLeft( bodyRight );
1346
1347 //Visit pExtra
1348 if( pExtra ){
1349 mpRightMost = mpGraph->Add( SmCaretPos( pExtra, 0 ), left );
1350 pExtra->Accept( this );
1351 mpRightMost->SetRight( bodyLeft );
1352 }
1353
1355}
1356
1357
1362{
1366}
1367
1375{
1376}
1377
1382{
1386}
1387
1407{
1408 SmNode* pBody = pNode->Body();
1409
1411 *right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
1412
1413 if( pBody->GetType() != SmNodeType::Bracebody ) {
1414 mpRightMost = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
1415 left->SetRight( mpRightMost );
1416 }else
1417 mpRightMost = left;
1418
1419 pBody->Accept( this );
1421 right->SetLeft( mpRightMost );
1422
1424}
1425
1439{
1440 SmNode *pAttr = pNode->Attribute(),
1441 *pBody = pNode->Body();
1442 assert(pAttr);
1443 assert(pBody);
1444
1446 *attrLeft,
1447 *bodyLeft,
1448 *bodyRight,
1449 *right;
1450
1451 //Creating bodyleft
1452 bodyLeft = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
1453 left->SetRight( bodyLeft );
1454
1455 //Creating right
1456 right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
1457
1458 //Visit the body
1459 mpRightMost = bodyLeft;
1460 pBody->Accept( this );
1461 bodyRight = mpRightMost;
1462 bodyRight->SetRight( right );
1463 right->SetLeft( bodyRight );
1464
1465 //Create attrLeft
1466 attrLeft = mpGraph->Add( SmCaretPos( pAttr, 0 ), left );
1467
1468 //Visit attribute
1469 mpRightMost = attrLeft;
1470 pAttr->Accept( this );
1472
1473 //Set return value
1475}
1476
1477//Consider these single symbols
1479{
1483}
1485{
1489}
1491{
1495}
1496
1498{
1499 //Do nothing
1500}
1501
1503{
1504 //Do nothing
1505}
1507{
1508 //Do nothing
1509}
1510
1511// SmCloningVisitor
1512
1514{
1515 SmNode* pCurrResult = mpResult;
1516 pNode->Accept( this );
1517 SmNode* pClone = mpResult;
1518 mpResult = pCurrResult;
1519 return pClone;
1520}
1521
1522void SmCloningVisitor::CloneNodeAttr( SmNode const * pSource, SmNode* pTarget )
1523{
1524 pTarget->SetScaleMode( pSource->GetScaleMode( ) );
1525 //Other attributes are set when prepare or arrange is executed
1526 //and may depend on stuff not being cloned here.
1527}
1528
1530{
1531 //Cache current result
1532 SmNode* pCurrResult = mpResult;
1533
1534 //Create array for holding clones
1535 size_t nSize = pSource->GetNumSubNodes( );
1536 SmNodeArray aNodes( nSize );
1537
1538 //Clone children
1539 for (size_t i = 0; i < nSize; ++i)
1540 {
1541 SmNode* pKid;
1542 if( nullptr != ( pKid = pSource->GetSubNode( i ) ) )
1543 pKid->Accept( this );
1544 else
1545 mpResult = nullptr;
1546 aNodes[i] = mpResult;
1547 }
1548
1549 //Set subnodes of pTarget
1550 pTarget->SetSubNodes( std::move(aNodes) );
1551
1552 //Restore result as where prior to call
1553 mpResult = pCurrResult;
1554}
1555
1557{
1558 SmTableNode* pClone = new SmTableNode( pNode->GetToken( ) );
1559 pClone->SetSelection( pNode->GetSelection() );
1560 CloneNodeAttr( pNode, pClone );
1561 CloneKids( pNode, pClone );
1562 mpResult = pClone;
1563}
1564
1566{
1567 SmBraceNode* pClone = new SmBraceNode( pNode->GetToken( ) );
1568 pClone->SetSelection( pNode->GetSelection() );
1569 CloneNodeAttr( pNode, pClone );
1570 CloneKids( pNode, pClone );
1571 mpResult = pClone;
1572}
1573
1575{
1576 SmBracebodyNode* pClone = new SmBracebodyNode( pNode->GetToken( ) );
1577 pClone->SetSelection( pNode->GetSelection() );
1578 CloneNodeAttr( pNode, pClone );
1579 CloneKids( pNode, pClone );
1580 mpResult = pClone;
1581}
1582
1584{
1585 SmOperNode* pClone = new SmOperNode( pNode->GetToken( ) );
1586 pClone->SetSelection( pNode->GetSelection() );
1587 CloneNodeAttr( pNode, pClone );
1588 CloneKids( pNode, pClone );
1589 mpResult = pClone;
1590}
1591
1593{
1594 SmAlignNode* pClone = new SmAlignNode( pNode->GetToken( ) );
1595 pClone->SetSelection( pNode->GetSelection() );
1596 CloneNodeAttr( pNode, pClone );
1597 CloneKids( pNode, pClone );
1598 mpResult = pClone;
1599}
1600
1602{
1603 SmAttributeNode* pClone = new SmAttributeNode( pNode->GetToken( ) );
1604 pClone->SetSelection( pNode->GetSelection() );
1605 CloneNodeAttr( pNode, pClone );
1606 CloneKids( pNode, pClone );
1607 mpResult = pClone;
1608}
1609
1611{
1612 SmFontNode* pClone = new SmFontNode( pNode->GetToken( ) );
1613 pClone->SetSelection( pNode->GetSelection() );
1614 pClone->SetSizeParameter( pNode->GetSizeParameter( ), pNode->GetSizeType( ) );
1615 CloneNodeAttr( pNode, pClone );
1616 CloneKids( pNode, pClone );
1617 mpResult = pClone;
1618}
1619
1621{
1622 SmUnHorNode* pClone = new SmUnHorNode( pNode->GetToken( ) );
1623 pClone->SetSelection( pNode->GetSelection() );
1624 CloneNodeAttr( pNode, pClone );
1625 CloneKids( pNode, pClone );
1626 mpResult = pClone;
1627}
1628
1630{
1631 SmBinHorNode* pClone = new SmBinHorNode( pNode->GetToken( ) );
1632 pClone->SetSelection( pNode->GetSelection() );
1633 CloneNodeAttr( pNode, pClone );
1634 CloneKids( pNode, pClone );
1635 mpResult = pClone;
1636}
1637
1639{
1640 SmBinVerNode* pClone = new SmBinVerNode( pNode->GetToken( ) );
1641 pClone->SetSelection( pNode->GetSelection() );
1642 CloneNodeAttr( pNode, pClone );
1643 CloneKids( pNode, pClone );
1644 mpResult = pClone;
1645}
1646
1648{
1649 SmBinDiagonalNode *pClone = new SmBinDiagonalNode( pNode->GetToken( ) );
1650 pClone->SetSelection( pNode->GetSelection() );
1651 pClone->SetAscending( pNode->IsAscending( ) );
1652 CloneNodeAttr( pNode, pClone );
1653 CloneKids( pNode, pClone );
1654 mpResult = pClone;
1655}
1656
1658{
1659 SmSubSupNode *pClone = new SmSubSupNode( pNode->GetToken( ) );
1660 pClone->SetSelection( pNode->GetSelection() );
1661 pClone->SetUseLimits( pNode->IsUseLimits( ) );
1662 CloneNodeAttr( pNode, pClone );
1663 CloneKids( pNode, pClone );
1664 mpResult = pClone;
1665}
1666
1668{
1669 SmMatrixNode *pClone = new SmMatrixNode( pNode->GetToken( ) );
1670 pClone->SetSelection( pNode->GetSelection() );
1671 pClone->SetRowCol( pNode->GetNumRows( ), pNode->GetNumCols( ) );
1672 CloneNodeAttr( pNode, pClone );
1673 CloneKids( pNode, pClone );
1674 mpResult = pClone;
1675}
1676
1678{
1679 mpResult = new SmPlaceNode( pNode->GetToken( ) );
1680 mpResult->SetSelection( pNode->GetSelection() );
1681 CloneNodeAttr( pNode, mpResult );
1682}
1683
1685{
1686 SmTextNode* pClone = new SmTextNode( pNode->GetToken( ), pNode->GetFontDesc( ) );
1687 pClone->SetSelection( pNode->GetSelection() );
1688 pClone->ChangeText( pNode->GetText( ) );
1689 CloneNodeAttr( pNode, pClone );
1690 mpResult = pClone;
1691}
1692
1694{
1695 mpResult = new SmSpecialNode( pNode->GetToken( ) );
1696 mpResult->SetSelection( pNode->GetSelection() );
1697 CloneNodeAttr( pNode, mpResult );
1698}
1699
1701{
1702 mpResult = new SmGlyphSpecialNode( pNode->GetToken( ) );
1703 mpResult->SetSelection( pNode->GetSelection() );
1704 CloneNodeAttr( pNode, mpResult );
1705}
1706
1708{
1709 mpResult = new SmMathSymbolNode( pNode->GetToken( ) );
1710 mpResult->SetSelection( pNode->GetSelection() );
1711 CloneNodeAttr( pNode, mpResult );
1712}
1713
1715{
1716 SmBlankNode* pClone = new SmBlankNode( pNode->GetToken( ) );
1717 pClone->SetSelection( pNode->GetSelection() );
1718 pClone->SetBlankNum( pNode->GetBlankNum( ) );
1719 mpResult = pClone;
1720 CloneNodeAttr( pNode, mpResult );
1721}
1722
1724{
1725 mpResult = new SmErrorNode( pNode->GetToken( ) );
1726 mpResult->SetSelection( pNode->GetSelection() );
1727 CloneNodeAttr( pNode, mpResult );
1728}
1729
1731{
1732 SmLineNode* pClone = new SmLineNode( pNode->GetToken( ) );
1733 pClone->SetSelection( pNode->GetSelection() );
1734 CloneNodeAttr( pNode, pClone );
1735 CloneKids( pNode, pClone );
1736 mpResult = pClone;
1737}
1738
1740{
1741 SmExpressionNode* pClone = new SmExpressionNode( pNode->GetToken( ) );
1742 pClone->SetSelection( pNode->GetSelection() );
1743 CloneNodeAttr( pNode, pClone );
1744 CloneKids( pNode, pClone );
1745 mpResult = pClone;
1746}
1747
1749{
1750 mpResult = new SmPolyLineNode( pNode->GetToken( ) );
1751 mpResult->SetSelection( pNode->GetSelection() );
1752 CloneNodeAttr( pNode, mpResult );
1753}
1754
1756{
1757 SmRootNode* pClone = new SmRootNode( pNode->GetToken( ) );
1758 pClone->SetSelection( pNode->GetSelection() );
1759 CloneNodeAttr( pNode, pClone );
1760 CloneKids( pNode, pClone );
1761 mpResult = pClone;
1762}
1763
1765{
1766 mpResult = new SmRootSymbolNode( pNode->GetToken( ) );
1767 mpResult->SetSelection( pNode->GetSelection() );
1768 CloneNodeAttr( pNode, mpResult );
1769}
1770
1772{
1773 mpResult = new SmRectangleNode( pNode->GetToken( ) );
1774 mpResult->SetSelection( pNode->GetSelection() );
1775 CloneNodeAttr( pNode, mpResult );
1776}
1777
1779{
1780 SmVerticalBraceNode* pClone = new SmVerticalBraceNode( pNode->GetToken( ) );
1781 pClone->SetSelection( pNode->GetSelection() );
1782 CloneNodeAttr( pNode, pClone );
1783 CloneKids( pNode, pClone );
1784 mpResult = pClone;
1785}
1786
1787// SmSelectionDrawingVisitor
1788
1790 : SmSelectionRectanglesVisitor( rDevice, pTree )
1791{
1792 //Draw selection if there's any
1793 if(GetSelection().IsEmpty()) return;
1794
1795 tools::Rectangle aSelectionArea = GetSelection() + rOffset;
1796
1797 //Save device state
1799 //Change colors
1800 rDevice.SetLineColor( );
1801 rDevice.SetFillColor( COL_LIGHTGRAY );
1802
1803 //Draw rectangle
1804 rDevice.DrawRect( aSelectionArea );
1805
1806 //Restore device state
1807 rDevice.Pop( );
1808}
1809
1810// SmSelectionRectanglesVisitor
1811
1813 : mrDev(rDevice)
1814{
1815 // Visit everything
1816 SAL_WARN_IF(!pTree, "starmath", "pTree can't be null!");
1817 if (pTree)
1818 pTree->Accept(this);
1819}
1820
1822{
1823 if( pNode->IsSelected( ) )
1824 ExtendSelectionArea( pNode->AsRectangle( ) );
1825 VisitChildren( pNode );
1826}
1827
1829{
1830 if(pNode->GetNumSubNodes() == 0)
1831 return;
1832 for( auto pChild : *static_cast<SmStructureNode*>(pNode) )
1833 {
1834 if(!pChild)
1835 continue;
1836 pChild->Accept( this );
1837 }
1838}
1839
1841{
1842 if( !pNode->IsSelected())
1843 return;
1844
1846
1847 mrDev.SetFont( pNode->GetFont( ) );
1848 Point Position = pNode->GetTopLeft( );
1849 tools::Long left = Position.getX( ) + mrDev.GetTextWidth( pNode->GetText( ), 0, pNode->GetSelectionStart( ) );
1850 tools::Long right = Position.getX( ) + mrDev.GetTextWidth( pNode->GetText( ), 0, pNode->GetSelectionEnd( ) );
1851 tools::Long top = Position.getY( );
1852 tools::Long bottom = top + pNode->GetHeight( );
1854
1855 ExtendSelectionArea( rect );
1856
1857 mrDev.Pop( );
1858}
1859
1860// SmNodeToTextVisitor
1861
1863{
1864 pNode->Accept( this );
1865 maCmdText.stripEnd(' ');
1866 rText = maCmdText.makeStringAndClear();
1867}
1868
1870{
1871 if( pNode->GetToken( ).eType == TBINOM ) {
1872 Append(u"{ binom");
1873 LineToText( pNode->GetSubNode( 0 ) );
1874 LineToText( pNode->GetSubNode( 1 ) );
1875 Append(u"} ");
1876 } else if( pNode->GetToken( ).eType == TSTACK ) {
1877 Append(u"stack{ ");
1878 bool bFirst = true;
1879 for( auto pChild : *pNode )
1880 {
1881 if(!pChild)
1882 continue;
1883 if(bFirst)
1884 bFirst = false;
1885 else
1886 {
1887 Separate( );
1888 Append(u"# ");
1889 }
1890 LineToText( pChild );
1891 }
1892 Separate( );
1893 Append(u"}");
1894 } else { //Assume it's a toplevel table, containing lines
1895 bool bFirst = true;
1896 for( auto pChild : *pNode )
1897 {
1898 if(!pChild)
1899 continue;
1900 if(bFirst)
1901 bFirst = false;
1902 else
1903 {
1904 Separate( );
1905 Append(u"newline");
1906 }
1907 Separate( );
1908 pChild->Accept( this );
1909 }
1910 }
1911}
1912
1914{
1915 if ( pNode->GetToken().eType == TEVALUATE )
1916 {
1917 SmNode *pBody = pNode->Body();
1918 Append(u"evaluate { ");
1919 pBody->Accept( this );
1920 Append(u"} ");
1921 }
1922 else{
1923 SmNode *pLeftBrace = pNode->OpeningBrace(),
1924 *pBody = pNode->Body(),
1925 *pRightBrace = pNode->ClosingBrace();
1926 //Handle special case where it's absolute function
1927 if( pNode->GetToken( ).eType == TABS ) {
1928 Append(u"abs");
1929 LineToText( pBody );
1930 } else {
1931 if( pNode->GetScaleMode( ) == SmScaleMode::Height )
1932 Append(u"left ");
1933 pLeftBrace->Accept( this );
1934 Separate( );
1935 pBody->Accept( this );
1936 Separate( );
1937 if( pNode->GetScaleMode( ) == SmScaleMode::Height )
1938 Append(u"right ");
1939 pRightBrace->Accept( this );
1940 }
1941 }
1942}
1943
1945{
1946 for( auto pChild : *pNode )
1947 {
1948 if(!pChild)
1949 continue;
1950 Separate( );
1951 pChild->Accept( this );
1952 }
1953}
1954
1956{
1957 Append( pNode->GetToken( ).aText );
1958 Separate( );
1959 if( pNode->GetToken( ).eType == TOPER ){
1960 //There's an SmGlyphSpecialNode if eType == TOPER
1961 if( pNode->GetSubNode( 0 )->GetType( ) == SmNodeType::SubSup )
1962 Append( pNode->GetSubNode( 0 )->GetSubNode( 0 )->GetToken( ).aText );
1963 else
1964 Append( pNode->GetSubNode( 0 )->GetToken( ).aText );
1965 }
1966 if( pNode->GetSubNode( 0 )->GetType( ) == SmNodeType::SubSup ) {
1967 SmSubSupNode *pSubSup = static_cast<SmSubSupNode*>( pNode->GetSubNode( 0 ) );
1968 SmNode* pChild = pSubSup->GetSubSup( LSUP );
1969 if( pChild ) {
1970 Separate( );
1971 Append(u"lsup { ");
1972 LineToText( pChild );
1973 Append(u"} ");
1974 }
1975 pChild = pSubSup->GetSubSup( LSUB );
1976 if( pChild ) {
1977 Separate( );
1978 Append(u"lsub { ");
1979 LineToText( pChild );
1980 Append(u"} ");
1981 }
1982 pChild = pSubSup->GetSubSup( RSUP );
1983 if( pChild ) {
1984 Separate( );
1985 Append(u"^ { ");
1986 LineToText( pChild );
1987 Append(u"} ");
1988 }
1989 pChild = pSubSup->GetSubSup( RSUB );
1990 if( pChild ) {
1991 Separate( );
1992 Append(u"_ { ");
1993 LineToText( pChild );
1994 Append(u"} ");
1995 }
1996 pChild = pSubSup->GetSubSup( CSUP );
1997 if( pChild ) {
1998 Separate( );
1999 if (pSubSup->IsUseLimits())
2000 Append(u"to { ");
2001 else
2002 Append(u"csup { ");
2003 LineToText( pChild );
2004 Append(u"} ");
2005 }
2006 pChild = pSubSup->GetSubSup( CSUB );
2007 if( pChild ) {
2008 Separate( );
2009 if (pSubSup->IsUseLimits())
2010 Append(u"from { ");
2011 else
2012 Append(u"csub { ");
2013 LineToText( pChild );
2014 Append(u"} ");
2015 }
2016 }
2017 LineToText( pNode->GetSubNode( 1 ) );
2018}
2019
2021{
2022 Append( pNode->GetToken( ).aText );
2023 LineToText( pNode->GetSubNode( 0 ) );
2024}
2025
2027{
2028 Append( pNode->GetToken( ).aText );
2029 LineToText( pNode->Body() );
2030}
2031
2033{
2034 sal_uInt32 nc;
2035 sal_uInt8 nr, ng, nb;
2036 switch ( pNode->GetToken( ).eType )
2037 {
2038 case TBOLD:
2039 Append(u"bold ");
2040 break;
2041 case TNBOLD:
2042 Append(u"nbold ");
2043 break;
2044 case TITALIC:
2045 Append(u"italic ");
2046 break;
2047 case TNITALIC:
2048 Append(u"nitalic ");
2049 break;
2050 case TPHANTOM:
2051 Append(u"phantom ");
2052 break;
2053 case TSIZE:
2054 {
2055 Append(u"size ");
2056 switch ( pNode->GetSizeType( ) )
2057 {
2058 case FontSizeType::PLUS:
2059 Append(u"+");
2060 break;
2062 Append(u"-");
2063 break;
2065 Append(u"*");
2066 break;
2068 Append(u"/");
2069 break;
2071 default:
2072 break;
2073 }
2074 Append( ::rtl::math::doubleToUString(
2075 static_cast<double>( pNode->GetSizeParameter( ) ),
2076 rtl_math_StringFormat_Automatic,
2077 rtl_math_DecimalPlaces_Max, '.', true ) );
2078 Separate( );
2079 }
2080 break;
2081
2082 case TDVIPSNAMESCOL:
2083 Append(u"color dvip ");
2084 nc = pNode->GetToken().cMathChar.toUInt32(16);
2086 break;
2087 case THTMLCOL:
2088 case TMATHMLCOL:
2089 case TICONICCOL:
2090 Append(u"color ");
2091 nc = pNode->GetToken().cMathChar.toUInt32(16);
2093 break;
2094 case TRGB:
2095 nc = pNode->GetToken().cMathChar.toUInt32(16);
2096 Append(u"color rgb ");
2097 nb = nc % 256;
2098 nc /= 256;
2099 ng = nc % 256;
2100 nc /= 256;
2101 nr = nc % 256;
2102 Append(OUString::number(nr));
2103 Separate();
2104 Append(OUString::number(ng));
2105 Separate();
2106 Append(OUString::number(nb));
2107 Separate();
2108 break;
2109 case TRGBA:
2110 Append(u"color rgba ");
2111 nc = pNode->GetToken().cMathChar.toUInt32(16);
2112 nb = nc % 256;
2113 nc /= 256;
2114 ng = nc % 256;
2115 nc /= 256;
2116 nr = nc % 256;
2117 nc /= 256;
2118 Append(OUString::number(nr));
2119 Separate();
2120 Append(OUString::number(ng));
2121 Separate();
2122 Append(OUString::number(nb));
2123 Separate();
2124 Append(OUString::number(nc));
2125 Separate();
2126 break;
2127 case THEX:
2128 Append(u"color hex ");
2129 nc = pNode->GetToken().cMathChar.toUInt32(16);
2130 Append(OUString::number(nc,16));
2131 Separate();
2132 break;
2133 case TSANS:
2134 Append(u"font sans ");
2135 break;
2136 case TSERIF:
2137 Append(u"font serif ");
2138 break;
2139 case TFIXED:
2140 Append(u"font fixed ");
2141 break;
2142 default:
2143 break;
2144 }
2145 LineToText( pNode->GetSubNode( 1 ) );
2146}
2147
2149{
2150 if(pNode->GetSubNode( 1 )->GetToken( ).eType == TFACT)
2151 {
2152 // visit children in the reverse order
2153 for( auto it = pNode->rbegin(); it != pNode->rend(); ++it )
2154 {
2155 auto pChild = *it;
2156 if(!pChild)
2157 continue;
2158 Separate( );
2159 pChild->Accept( this );
2160 }
2161 }
2162 else
2163 {
2164 for( auto pChild : *pNode )
2165 {
2166 if(!pChild)
2167 continue;
2168 Separate( );
2169 pChild->Accept( this );
2170 }
2171 }
2172}
2173
2175{
2176 const SmNode *pParent = pNode->GetParent();
2177 bool bBraceNeeded = pParent && pParent->GetType() == SmNodeType::Font;
2178 SmNode *pLeft = pNode->LeftOperand(),
2179 *pOper = pNode->Symbol(),
2180 *pRight = pNode->RightOperand();
2181 Separate( );
2182 if (bBraceNeeded)
2183 Append(u"{ ");
2184 pLeft->Accept( this );
2185 Separate( );
2186 pOper->Accept( this );
2187 Separate( );
2188 pRight->Accept( this );
2189 Separate( );
2190 if (bBraceNeeded)
2191 Append(u"} ");
2192}
2193
2195{
2196 if( pNode->GetToken().eType == TOVER ){
2197 SmNode *pNum = pNode->GetSubNode( 0 ),
2198 *pDenom = pNode->GetSubNode( 2 );
2199 Append(u"{ ");
2200 LineToText( pNum );
2201 Append(u"over");
2202 LineToText( pDenom );
2203 Append(u"} ");
2204 } else{
2205 SmNode *pNum = pNode->GetSubNode( 0 ),
2206 *pDenom = pNode->GetSubNode( 2 );
2207 Append(u"{ frac {");
2208 LineToText( pNum );
2209 Append(u"} {");
2210 LineToText( pDenom );
2211 Append(u"} }");
2212 }
2213}
2214
2216{
2217 SmNode *pLeftOperand = pNode->GetSubNode( 0 ),
2218 *pRightOperand = pNode->GetSubNode( 1 );
2219 Append(u"{ ");
2220 LineToText( pLeftOperand );
2221 Separate( );
2222 Append(u"wideslash ");
2223 LineToText( pRightOperand );
2224 Append(u"} ");
2225}
2226
2228{
2229 if( pNode->GetToken().eType == TEVALUATE )
2230 {
2231 Append(u"evaluate { ");
2232 pNode->GetSubNode( 0 )->GetSubNode( 1 )->Accept(this);
2233 Append(u"} ");
2234 SmNode* pChild = pNode->GetSubSup( RSUP );
2235 if( pChild ) {
2236 Separate( );
2237 Append(u"to { ");
2238 LineToText( pChild );
2239 Append(u"} ");
2240 }
2241 pChild = pNode->GetSubSup( RSUB );
2242 if( pChild ) {
2243 Separate( );
2244 Append(u"from { ");
2245 LineToText( pChild );
2246 Append(u"} ");
2247 }
2248 }
2249 else
2250 {
2251 LineToText( pNode->GetBody( ) );
2252 SmNode *pChild = pNode->GetSubSup( LSUP );
2253 if( pChild ) {
2254 Separate( );
2255 Append(u"lsup ");
2256 LineToText( pChild );
2257 }
2258 pChild = pNode->GetSubSup( LSUB );
2259 if( pChild ) {
2260 Separate( );
2261 Append(u"lsub ");
2262 LineToText( pChild );
2263 }
2264 pChild = pNode->GetSubSup( RSUP );
2265 if( pChild ) {
2266 Separate( );
2267 Append(u"^ ");
2268 LineToText( pChild );
2269 }
2270 pChild = pNode->GetSubSup( RSUB );
2271 if( pChild ) {
2272 Separate( );
2273 Append(u"_ ");
2274 LineToText( pChild );
2275 }
2276 pChild = pNode->GetSubSup( CSUP );
2277 if( pChild ) {
2278 Separate( );
2279 if (pNode->IsUseLimits())
2280 Append(u"to ");
2281 else
2282 Append(u"csup ");
2283 LineToText( pChild );
2284 }
2285 pChild = pNode->GetSubSup( CSUB );
2286 if( pChild ) {
2287 Separate( );
2288 if (pNode->IsUseLimits())
2289 Append(u"from ");
2290 else
2291 Append(u"csub ");
2292 LineToText( pChild );
2293 }
2294 }
2295}
2296
2298{
2299 Append(u"matrix{");
2300 for (size_t i = 0; i < pNode->GetNumRows(); ++i)
2301 {
2302 for (size_t j = 0; j < pNode->GetNumCols( ); ++j)
2303 {
2304 SmNode* pSubNode = pNode->GetSubNode( i * pNode->GetNumCols( ) + j );
2305 Separate( );
2306 if (pSubNode)
2307 pSubNode->Accept( this );
2308 Separate( );
2309 if (j != pNode->GetNumCols() - 1U)
2310 Append(u"#");
2311 }
2312 Separate( );
2313 if (i != pNode->GetNumRows() - 1U)
2314 Append(u"##");
2315 }
2316 Append(u"} ");
2317}
2318
2320{
2321 Append(u"<?>");
2322}
2323
2325{
2326 SmTokenType type = pNode->GetToken( ).eType;
2327 switch(type){
2328 case TTEXT:
2329 Append(u"\"");
2330 Append( pNode->GetToken().aText );
2331 Append(u"\"");
2332 break;
2333 case TNUMBER:
2334 Append( pNode->GetToken().aText );
2335 break;
2336 case TIDENT:
2337 Append( pNode->GetToken().aText );
2338 break;
2339 case TFUNC:
2340 Append(u"func ");
2341 Append( pNode->GetToken().aText );
2342 break;
2343 case THEX:
2344 Append(u"hex ");
2345 Append( pNode->GetToken().aText );
2346 break;
2347 default:
2348 Append( pNode->GetToken().aText );
2349 }
2350 Separate( );
2351}
2352
2354{
2355 SmTokenType type = pNode->GetToken().eType;
2356 switch(type){
2357 case TLIMSUP:
2358 Append(u"lim sup ");
2359 break;
2360 case TLIMINF:
2361 Append(u"lim inf ");
2362 break;
2363 default:
2364 Append( pNode->GetToken().aText );
2365 break;
2366 }
2367}
2368
2370{
2371 if( pNode->GetToken( ).eType == TBOPER )
2372 Append(u"boper ");
2373 else
2374 Append(u"uoper ");
2375 Append( pNode->GetToken( ).aText );
2376}
2377
2378//TODO to improve this it is required to improve mathmlimport.
2380{
2381 if ( ( pNode->GetToken().nGroup & TG::LBrace )
2382 || ( pNode->GetToken().nGroup & TG::RBrace )
2383 || ( pNode->GetToken().nGroup & TG::Sum )
2384 || ( pNode->GetToken().nGroup & TG::Product )
2385 || ( pNode->GetToken().nGroup & TG::Relation )
2386 || ( pNode->GetToken().nGroup & TG::UnOper )
2387 || ( pNode->GetToken().nGroup & TG::Oper )
2388 ) {
2389 Append( pNode->GetToken().aText );
2390 return;
2391 }
2392 sal_Unicode cChar = pNode->GetToken().cMathChar[0];
2393 Separate( );
2394 switch(cChar){
2395 case MS_NONE:
2396 Append(u"none");
2397 break;
2398 case '{':
2399 Append(u"{");
2400 break;
2401 case '}':
2402 Append(u"}");
2403 break;
2404 case MS_VERTLINE:
2405 Append(u"mline");
2406 break;
2407 case MS_TILDE:
2408 Append(u"\"~\"");
2409 break;
2410 case MS_RIGHTARROW:
2411 if( pNode->GetToken().eType == TTOWARD ) Append(u"toward");
2412 else Append(u"rightarrow");
2413 break;
2414 case MS_LEFTARROW:
2415 Append(u"leftarrow");
2416 break;
2417 case MS_UPARROW:
2418 Append(u"uparrow");
2419 break;
2420 case MS_DOWNARROW:
2421 Append(u"downarrow");
2422 break;
2423 case MS_LAMBDABAR:
2424 Append(u"lambdabar");
2425 break;
2426 case MS_DOTSLOW:
2427 Append(u"dotslow");
2428 break;
2429 case MS_SETC:
2430 Append(u"setC");
2431 break;
2432 case MS_HBAR:
2433 Append(u"hbar");
2434 break;
2435 case MS_IM:
2436 Append(u"Im");
2437 break;
2438 case MS_SETN:
2439 Append(u"setN");
2440 break;
2441 case MS_WP:
2442 Append(u"wp");
2443 break;
2444 case MS_LAPLACE:
2445 Append(u"laplace");
2446 break;
2447 case MS_SETQ:
2448 Append(u"setQ");
2449 break;
2450 case MS_RE:
2451 Append(u"Re");
2452 break;
2453 case MS_SETR:
2454 Append(u"setR");
2455 break;
2456 case MS_SETZ:
2457 Append(u"setZ");
2458 break;
2459 case MS_ALEPH:
2460 Append(u"aleph");
2461 break;
2462 case 0x0362:
2463 Append(u"widevec");
2464 break;
2465 case MS_DLARROW:
2466 Append(u"dlarrow");
2467 break;
2468 case MS_DRARROW:
2469 Append(u"drarrow");
2470 break;
2471 case MS_DLRARROW:
2472 Append(u"dlrarrow");
2473 break;
2474 case MS_FORALL:
2475 Append(u"forall");
2476 break;
2477 case MS_PARTIAL:
2478 Append(u"partial");
2479 break;
2480 case MS_EXISTS:
2481 Append(u"exists");
2482 break;
2483 case MS_NOTEXISTS:
2484 Append(u"notexists");
2485 break;
2486 case MS_EMPTYSET:
2487 Append(u"emptyset");
2488 break;
2489 case MS_NABLA:
2490 Append(u"nabla");
2491 break;
2492 case MS_BACKEPSILON:
2493 Append(u"backepsilon");
2494 break;
2495 case MS_CIRC:
2496 Append(u"circ");
2497 break;
2498 case MS_INFINITY:
2499 Append(u"infinity");
2500 break;
2501 case 0x22b2: // NORMAL SUBGROUP OF
2502 Append(OUStringChar(cChar));
2503 break;
2504 case 0x22b3: // CONTAINS AS NORMAL SUBGROUP
2505 Append(OUStringChar(cChar));
2506 break;
2507 case MS_ORTHO:
2508 Append(u"ortho");
2509 break;
2510 case MS_DOTSVERT:
2511 Append(u"dotsvert");
2512 break;
2513 case MS_DOTSAXIS:
2514 Append(u"dotsaxis");
2515 break;
2516 case MS_DOTSUP:
2517 Append(u"dotsup");
2518 break;
2519 case MS_DOTSDOWN:
2520 Append(u"dotsdown");
2521 break;
2522 case '^':
2523 Append(u"^");
2524 break;
2525 case 0xe091:
2526 Append(u"widehat");
2527 break;
2528 case 0xe096:
2529 Append(u"widetilde");
2530 break;
2531 case 0xe098:
2532 Append(u"widevec");
2533 break;
2534 case 0xeb01: //no space
2535 case 0xeb08: //normal space
2536 break;
2537 case 0xef04: //tiny space
2538 case 0xef05: //tiny space
2539 case 0xeb02: //small space
2540 case 0xeb04: //medium space
2541 Append(u"`");
2542 break;
2543 case 0xeb05: //large space
2544 Append(u"~");
2545 break;
2546 case 0x3a9:
2547 Append(u"%OMEGA");
2548 break;
2549 default:
2550 Append(OUStringChar(cChar));
2551 break;
2552 }
2553}
2554
2556{
2557 sal_uInt16 nNum = pNode->GetBlankNum();
2558 if (nNum <= 0)
2559 return;
2560 sal_uInt16 nWide = nNum / 4;
2561 sal_uInt16 nNarrow = nNum % 4;
2562 for (sal_uInt16 i = 0; i < nWide; i++)
2563 Append(u"~");
2564 for (sal_uInt16 i = 0; i < nNarrow; i++)
2565 Append(u"`");
2566 Append(u" ");
2567}
2568
2570{
2571}
2572
2574{
2575 for( auto pChild : *pNode )
2576 {
2577 if(!pChild)
2578 continue;
2579 Separate( );
2580 pChild->Accept( this );
2581 }
2582}
2583
2585{
2586 bool bracketsNeeded = pNode->GetNumSubNodes() != 1 || pNode->GetSubNode(0)->GetType() == SmNodeType::BinHor;
2587 if (!bracketsNeeded)
2588 {
2589 const SmNode *pParent = pNode->GetParent();
2590 // nested subsups
2591 bracketsNeeded =
2592 pParent && pParent->GetType() == SmNodeType::SubSup &&
2593 pNode->GetNumSubNodes() == 1 &&
2594 pNode->GetSubNode(0)->GetType() == SmNodeType::SubSup;
2595 }
2596
2597 if (bracketsNeeded) {
2598 Append(u"{ ");
2599 }
2600 for( auto pChild : *pNode )
2601 {
2602 if(!pChild)
2603 continue;
2604 pChild->Accept( this );
2605 Separate( );
2606 }
2607 if (bracketsNeeded) {
2608 Append(u"} ");
2609 }
2610}
2611
2613{
2614}
2615
2617{
2618 SmNode *pExtra = pNode->GetSubNode( 0 ),
2619 *pBody = pNode->GetSubNode( 2 );
2620 if( pExtra ) {
2621 Append(u"nroot");
2622 LineToText( pExtra );
2623 } else
2624 Append(u"sqrt");
2625 LineToText( pBody );
2626}
2627
2629{
2630}
2631
2633{
2634}
2635
2637{
2638 SmNode *pBody = pNode->Body(),
2639 *pScript = pNode->Script();
2640 LineToText( pBody );
2641 Append( pNode->GetToken( ).aText );
2642 LineToText( pScript );
2643}
2644
2645/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
UBlockCode from
UBlockCode to
void SetWidth(double nWidth)
void DrawPolyLine(const tools::Polygon &rPoly)
void SetFont(const vcl::Font &rNewFont)
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
void DrawRect(const tools::Rectangle &rRect)
void DrawLine(const Point &rStartPt, const Point &rEndPt)
void SetLineColor()
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void SetFillColor()
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
void DrawStretchText(const Point &rStartPt, sal_Int32 nWidth, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1)
constexpr tools::Long Y() const
void Move(tools::Long nHorzMove, tools::Long nVertMove)
tools::Long AdjustY(tools::Long nVertMove)
constexpr tools::Long X() const
Node used for alignment.
Definition: node.hxx:1856
Attribute node.
Definition: node.hxx:1890
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
Binary diagonal node.
Definition: node.hxx:1461
bool IsAscending() const
Checks if it is of ascending type.
Definition: node.hxx:1491
void SetAscending(bool bVal)
Sets if the wideslash is ascending to bVal.
Definition: node.hxx:1498
Binary horizontal node.
Definition: node.hxx:1368
const SmNode * Symbol() const
Returns the node containing the data of the binary operator.
Definition: node.hxx:1393
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
Binary horizontal node.
Definition: node.hxx:1425
Node for whitespace.
Definition: node.hxx:2056
sal_uInt16 GetBlankNum() const
Definition: node.hxx:2066
void SetBlankNum(sal_uInt16 nNumber)
Definition: node.hxx:2067
Node for brace construction.
Definition: node.hxx:1646
const SmMathSymbolNode * OpeningBrace() const
Returns the node containing the data of the opening brace.
Definition: node.hxx:1655
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 ProcessUnderline(Point from, Point to) override
Definition: visitors.cxx:255
SmCaretDrawingVisitor(OutputDevice &rDevice, SmCaretPos position, Point offset, bool caretVisible)
Given position and device this constructor will draw the caret.
Definition: visitors.cxx:235
virtual void ProcessCaretLine(Point from, Point to) override
Definition: visitors.cxx:245
A line that represents a caret.
Definition: caret.hxx:61
Point maOffset
Offset to draw from.
Definition: visitors.hxx:138
virtual void ProcessCaretLine(Point from, Point to)=0
SmCaretLinesVisitor(OutputDevice &rDevice, SmCaretPos position, Point offset)
Definition: visitors.cxx:159
OutputDevice & mrDev
Definition: visitors.hxx:135
void Visit(SmTextNode *pNode) override
Definition: visitors.cxx:180
void DefaultVisit(SmNode *pNode) override
Default method for drawing pNodes.
Definition: visitors.cxx:203
SmCaretPos maPos
Definition: visitors.hxx:136
virtual void ProcessUnderline(Point from, Point to)=0
OutputDevice & getDev()
Definition: visitors.hxx:127
VclPtr< OutputDevice > mpDev
Definition: visitors.hxx:197
void DefaultVisit(SmNode *pNode) override
Default method for computing lines for pNodes.
Definition: visitors.cxx:285
void Visit(SmTextNode *pNode) override
Definition: visitors.cxx:265
SmCaretPosGraphBuildingVisitor(SmNode *pRootNode)
Builds a caret position graph for pRootNode.
Definition: visitors.cxx:759
void Visit(SmTableNode *pNode) override
Build SmCaretPosGraph for SmTableNode This method covers cases where SmTableNode is used in a binom o...
Definition: visitors.cxx:799
SmCaretPosGraphEntry * mpRightMost
Definition: visitors.hxx:372
std::unique_ptr< SmCaretPosGraph > mpGraph
Definition: visitors.hxx:373
virtual ~SmCaretPosGraphBuildingVisitor()
Definition: visitors.cxx:781
A graph over all caret positions.
Definition: caret.hxx:132
virtual void ProcessUnderline(Point from, Point to) override
Definition: visitors.cxx:231
tools::Rectangle maCaret
Definition: visitors.hxx:154
SmCaretRectanglesVisitor(OutputDevice &rDevice, SmCaretPos position)
Definition: visitors.cxx:224
virtual void ProcessCaretLine(Point from, Point to) override
Definition: visitors.cxx:230
SmNode * mpResult
Definition: visitors.hxx:419
void CloneKids(SmStructureNode *pSource, SmStructureNode *pTarget)
Clone children of pSource and give them to pTarget.
Definition: visitors.cxx:1529
SmNode * Clone(SmNode *pNode)
Clone a pNode.
Definition: visitors.cxx:1513
void Visit(SmTableNode *pNode) override
Definition: visitors.cxx:1556
static void CloneNodeAttr(SmNode const *pSource, SmNode *pTarget)
Clone attributes on a pNode.
Definition: visitors.cxx:1522
static SmNode * FindTopMostNodeInLine(SmNode *pSNode, bool MoveUpIfSelected=false)
Finds the topmost node in a visual line.
Definition: cursor.cxx:1109
virtual void DefaultVisit(SmNode *pNode)=0
Method invoked by Visit methods by default.
void Visit(SmTableNode *pNode) override
Definition: visitors.cxx:22
OutputDevice & mrDev
OutputDevice to draw on.
Definition: visitors.hxx:261
Point maPosition
Position to draw on the mrDev.
Definition: visitors.hxx:267
void Visit(SmTableNode *pNode) override
Definition: visitors.cxx:298
void DrawTextNode(SmTextNode *pNode)
Draw an SmTextNode or a subclass of this.
Definition: visitors.cxx:502
void DrawChildren(SmStructureNode *pNode)
Draw the children of a pNode This the default method, use by most pNodes.
Definition: visitors.cxx:527
void DrawSpecialNode(SmSpecialNode *pNode)
Draw an SmSpecialNode or a subclass of this
Definition: visitors.cxx:518
Error node, for parsing errors.
Definition: node.hxx:1097
Expression node.
Definition: node.hxx:1244
tools::Long GetBorderWidth() const
Definition: utility.cxx:218
Font node.
Definition: node.hxx:1932
void SetSizeParameter(const Fraction &rValue, FontSizeType nType)
Sets font size to rValue in nType mode.
Definition: node.hxx:1949
const Fraction & GetSizeParameter() const
Returns the font size.
Definition: node.hxx:1956
FontSizeType GetSizeType() const
Returns the font size type.
Definition: node.hxx:1963
Glyph node for custom operators.
Definition: node.hxx:926
A line.
Definition: node.hxx:1178
Math symbol node.
Definition: node.hxx:955
Matrix node.
Definition: node.hxx:2000
void SetRowCol(sal_uInt16 nMatrixRows, sal_uInt16 nMatrixCols)
Sets the dimensions of the matrix.
Definition: node.hxx:2028
sal_uInt16 GetNumRows() const
Gets the number of rows of the matrix.
Definition: node.hxx:2014
sal_uInt16 GetNumCols() const
Gets the number of columns of the matrix.
Definition: node.hxx:2020
OUStringBuffer maCmdText
Output text generated from the pNodes.
Definition: visitors.hxx:530
void LineToText(SmNode *pNode)
Extract text from a pNode that constitutes a line.
Definition: visitors.hxx:504
SmNodeToTextVisitor(SmNode *pNode, OUString &rText)
Definition: visitors.cxx:1862
void Separate()
Append a blank for separation, if needed.
Definition: visitors.hxx:524
void Append(std::u16string_view rText)
Appends rText to the OUStringBuffer ( maCmdText ).
Definition: visitors.hxx:515
void Visit(SmTableNode *pNode) override
Definition: visitors.cxx:1869
Definition: node.hxx:125
void SetSelection(ESelection aESelection)
Gets node position in input text.
Definition: node.hxx:400
SmScaleMode GetScaleMode() const
Gets the scale mode.
Definition: node.hxx:362
virtual void Accept(SmVisitor *pVisitor)=0
Accept a visitor.
virtual size_t GetNumSubNodes() const =0
Gets the number of subnodes.
const SmToken & GetToken() const
Gets the token.
Definition: node.hxx:387
virtual SmNode * GetSubNode(size_t nIndex)=0
Gets the subnode of index nIndex.
bool IsSelected() const
Checks if the node is selected.
Definition: node.hxx:430
void SetScaleMode(SmScaleMode eMode)
Sets the scale mode to eMode.
Definition: node.hxx:369
const SmStructureNode * GetParent() const
Gets the parent node of this node.
Definition: node.hxx:443
const ESelection & GetSelection() const
Gets node position in input text.
Definition: node.hxx:394
SmNodeType GetType() const
Gets the node type.
Definition: node.hxx:379
const SmFace & GetFont() const
Gets the font.
Definition: node.hxx:227
bool IsPhantom() const
Checks if it is a visible node rendered invisible.
Definition: node.hxx:191
void SetSelected(bool Selected)
Sets the node to Selected.
Definition: node.hxx:437
Operation Node.
Definition: node.hxx:1811
Place node.
Definition: node.hxx:1056
Polygon line node.
Definition: node.hxx:700
tools::Long GetWidth() const
Gets the width of the rect.
Definition: node.hxx:712
tools::Polygon & GetPolygon()
Gets the polygon to draw the node.
Definition: node.hxx:718
const Point & GetTopLeft() const
Definition: rect.hxx:124
tools::Long GetBaselineOffset() const
Definition: rect.hxx:147
tools::Long GetHeight() const
Definition: rect.hxx:132
tools::Long GetTop() const
Definition: rect.hxx:126
sal_uInt16 GetBorderWidth() const
Definition: rect.hxx:113
tools::Long GetWidth() const
Definition: rect.hxx:131
tools::Long GetLeft() const
Definition: rect.hxx:127
tools::Long GetRight() const
Definition: rect.hxx:129
tools::Rectangle AsRectangle() const
Definition: rect.hxx:211
Draws a rectangle.
Definition: node.hxx:665
Root node.
Definition: node.hxx:1307
Root symbol node.
Definition: node.hxx:1020
sal_uLong GetBodyWidth() const
Gets the body width.
Definition: node.hxx:1033
SmSelectionDrawingVisitor(OutputDevice &rDevice, SmNode *pTree, const Point &rOffset)
Draws a selection on rDevice for the selection on pTree.
Definition: visitors.cxx:1789
const tools::Rectangle & GetSelection()
Definition: visitors.hxx:437
void DefaultVisit(SmNode *pNode) override
Default visiting method.
Definition: visitors.cxx:1821
SmSelectionRectanglesVisitor(OutputDevice &rDevice, SmNode *pTree)
Definition: visitors.cxx:1812
void VisitChildren(SmNode *pNode)
Visit the children of a given pNode.
Definition: visitors.cxx:1828
OutputDevice & mrDev
Reference to drawing device.
Definition: visitors.hxx:441
void ExtendSelectionArea(const tools::Rectangle &rArea)
Extend the area that must be selected
Definition: visitors.hxx:445
void Visit(SmTextNode *pNode) override
Definition: visitors.cxx:1840
static void SetSelectedOnAll(SmNode *pSubTree, bool IsSelected=true)
Set IsSelected on all pNodes of pSubTree.
Definition: visitors.cxx:587
bool mbSelecting
The current state of this visitor This property changes when the visitor meets either maStartPos or m...
Definition: visitors.hxx:308
SmSetSelectionVisitor(SmCaretPos startPos, SmCaretPos endPos, SmNode *pNode)
Definition: visitors.cxx:546
void VisitCompositionNode(SmStructureNode *pNode)
Definition: visitors.cxx:660
void DefaultVisit(SmNode *pNode) override
Visit a selectable pNode Can be used to handle pNodes that can be selected, that doesn't have more Sm...
Definition: visitors.cxx:601
void Visit(SmBinHorNode *pNode) override
Definition: visitors.cxx:745
SmCaretPos maStartPos
Caret position where the selection starts.
Definition: visitors.hxx:300
SmCaretPos maEndPos
Caret position where the selection ends.
Definition: visitors.hxx:302
Special node for user defined characters.
Definition: node.hxx:878
Abstract baseclass for all composite node.
Definition: node.hxx:471
SmNodeArray::reverse_iterator rend()
Gets the first subnode.
Definition: node.hxx:582
virtual size_t GetNumSubNodes() const override
Gets the number of subnodes.
Definition: node.cxx:430
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
SmNodeArray::reverse_iterator rbegin()
Gets the last subnode.
Definition: node.hxx:576
Super- and subscript node.
Definition: node.hxx:1559
void SetUseLimits(bool bVal)
Sets if it is going to be used for a limit to bVal.
Definition: node.hxx:1586
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
bool IsUseLimits() const
Checks if it is going to be used for a limit.
Definition: node.hxx:1579
Table node.
Definition: node.hxx:1139
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
const OUString & GetText() const
Gets the node text.
Definition: node.hxx:782
sal_Int32 GetSelectionStart() const
Index within GetText() where the selection starts.
Definition: node.hxx:803
void SetSelectionEnd(sal_Int32 index)
Sets the index within GetText() where the selection ends to index.
Definition: node.hxx:824
void SetSelectionStart(sal_Int32 index)
Sets the index within GetText() where the selection starts to index.
Definition: node.hxx:817
sal_uInt16 GetFontDesc() const
Returns the font type being used (text, variable, symbol, ...).
Definition: node.hxx:769
sal_Int32 GetSelectionEnd() const
Index within GetText() where the selection ends.
Definition: node.hxx:810
void SetFont(const vcl::Font &rNewFont)
Definition: tmpdevice.cxx:62
void SetLineColor(const Color &rColor)
Definition: tmpdevice.hxx:40
void SetFillColor(const Color &rColor)
Definition: tmpdevice.hxx:41
Unary horizontal node.
Definition: node.hxx:1272
Node for vertical brace construction.
Definition: node.hxx:1750
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
void Move(tools::Long nHorzMove, tools::Long nVertMove)
tools::Rectangle GetBoundRect() const
constexpr Point TopLeft() const
void SetPos(const Point &rPoint)
tools::Long AdjustTop(tools::Long nVertMoveDelta)
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
constexpr bool IsEmpty() const
const Color & GetColor() const
void SetAlignment(TextAlign)
constexpr ::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
OString right
OString top
OString bottom
float u
ALIGN_BASELINE
#define SAL_WARN_IF(condition, area, stream)
def position(n=-1)
size
int i
end
SmColorTokenTableEntry Identify_Color_Parser(sal_uInt32 cColor)
Identifies color from color code cColor.
long Long
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
sal_uIntPtr sal_uLong
An entry in SmCaretPosGraph.
Definition: caret.hxx:111
void SetRight(SmCaretPosGraphEntry *right)
Definition: caret.hxx:124
Representation of caret position with an equation.
Definition: caret.hxx:17
bool IsValid() const
True, if this is a valid caret position.
Definition: caret.hxx:41
int nIndex
Index (invariant: non-negative) within the selected node.
Definition: caret.hxx:38
SmNode * pSelectedNode
Selected node.
Definition: caret.hxx:26
SmTokenType eType
Definition: token.hxx:213
OUString cMathChar
Definition: token.hxx:214
OUString aText
Definition: token.hxx:212
TG nGroup
Definition: token.hxx:217
@ Oper
@ RBrace
@ LBrace
@ Relation
@ Sum
@ UnOper
@ Product
SmTokenType
Definition: token.hxx:71
@ TSTACK
Definition: token.hxx:91
@ TBINOM
Definition: token.hxx:91
@ TTOWARD
Definition: token.hxx:86
@ TSIZE
Definition: token.hxx:115
@ TNITALIC
Definition: token.hxx:116
@ TBOPER
Definition: token.hxx:105
@ TLIMINF
Definition: token.hxx:86
@ TMATHMLCOL
Definition: token.hxx:147
@ TEVALUATE
Definition: token.hxx:132
@ TRGBA
Definition: token.hxx:146
@ TOVER
Definition: token.hxx:87
@ TOPER
Definition: token.hxx:83
@ TSERIF
Definition: token.hxx:119
@ TNBOLD
Definition: token.hxx:116
@ TNUMBER
Definition: token.hxx:124
@ 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
@ THTMLCOL
Definition: token.hxx:146
@ TFACT
Definition: token.hxx:144
@ TDVIPSNAMESCOL
Definition: token.hxx:146
@ TFIXED
Definition: token.hxx:119
@ TITALIC
Definition: token.hxx:116
@ TTEXT
Definition: token.hxx:124
@ TIDENT
Definition: token.hxx:124
@ THEX
Definition: token.hxx:146
@ TFUNC
Definition: token.hxx:139
@ TPHANTOM
Definition: token.hxx:115
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
sal_Unicode const MS_DOTSDOWN
Definition: types.hxx:117
sal_Unicode const MS_TILDE
Definition: types.hxx:142
sal_Unicode const MS_DOWNARROW
Definition: types.hxx:189
sal_Unicode const MS_INFINITY
Definition: types.hxx:42
sal_Unicode const MS_WP
Definition: types.hxx:106
sal_Unicode const MS_RIGHTARROW
Definition: types.hxx:188
sal_Unicode const MS_LEFTARROW
Definition: types.hxx:186
sal_Unicode const MS_SETN
Definition: types.hxx:191
sal_Unicode const MS_LAPLACE
Definition: types.hxx:87
sal_Unicode const MS_LAMBDABAR
Definition: types.hxx:184
sal_Unicode const MS_CIRC
Definition: types.hxx:51
sal_Unicode const MS_SETQ
Definition: types.hxx:193
sal_Unicode const MS_SETR
Definition: types.hxx:194
sal_Unicode const MS_ALEPH
Definition: types.hxx:103
sal_Unicode const MS_IM
Definition: types.hxx:104
sal_Unicode const MS_DRARROW
Definition: types.hxx:46
sal_Unicode const MS_NONE
Note: not listed here does not(!) mean "not used" (see alpha ... gamma for example)
Definition: types.hxx:39
sal_Unicode const MS_DLARROW
Definition: types.hxx:47
sal_Unicode const MS_NABLA
Definition: types.hxx:124
sal_Unicode const MS_DOTSUP
Definition: types.hxx:116
sal_Unicode const MS_DOTSLOW
Definition: types.hxx:113
sal_Unicode const MS_SETC
Definition: types.hxx:195
sal_Unicode const MS_SETZ
Definition: types.hxx:192
sal_Unicode const MS_FORALL
Definition: types.hxx:123
sal_Unicode const MS_NOTEXISTS
Definition: types.hxx:101
sal_Unicode const MS_PARTIAL
Definition: types.hxx:86
sal_Unicode const MS_UPARROW
Definition: types.hxx:187
sal_Unicode const MS_DOTSVERT
Definition: types.hxx:115
sal_Unicode const MS_DOTSAXIS
Definition: types.hxx:114
sal_Unicode const MS_HBAR
Definition: types.hxx:185
sal_Unicode const MS_EMPTYSET
Definition: types.hxx:163
sal_Unicode const MS_BACKEPSILON
Definition: types.hxx:102
sal_Unicode const MS_RE
Definition: types.hxx:105
sal_Unicode const MS_DLRARROW
Definition: types.hxx:48
sal_Unicode const MS_EXISTS
Definition: types.hxx:100
sal_Unicode const MS_VERTLINE
Definition: types.hxx:109
sal_Unicode const MS_ORTHO
Definition: types.hxx:112
ResultType type
sal_uInt64 left
const sal_uInt8 A