summaryrefslogtreecommitdiffstats
path: root/starmath/inc/visitors.hxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /starmath/inc/visitors.hxx
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'starmath/inc/visitors.hxx')
-rw-r--r--starmath/inc/visitors.hxx538
1 files changed, 538 insertions, 0 deletions
diff --git a/starmath/inc/visitors.hxx b/starmath/inc/visitors.hxx
new file mode 100644
index 0000000000..338e93432b
--- /dev/null
+++ b/starmath/inc/visitors.hxx
@@ -0,0 +1,538 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/** Visitors are an easy way to automating operations with nodes.
+ *
+ * The available visitors are:
+ * SmVisitor base class
+ * SmDefaultingVisitor default visitor
+ * SmDrawingVisitor draws formula
+ * SmCaretPosGraphBuildingVisitor position of the node inside starmath code
+ * SmCloningVisitor duplicate nodes
+ * SmNodeToTextVisitor create code from nodes
+ *
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include "node.hxx"
+#include "caret.hxx"
+
+/** Base class for visitors that visits a tree of SmNodes
+ * @remarks all methods have been left abstract to ensure that implementers
+ * don't forget to implement one.
+ */
+class SmVisitor
+{
+public:
+ virtual void Visit( SmTableNode* pNode ) = 0;
+ virtual void Visit( SmBraceNode* pNode ) = 0;
+ virtual void Visit( SmBracebodyNode* pNode ) = 0;
+ virtual void Visit( SmOperNode* pNode ) = 0;
+ virtual void Visit( SmAlignNode* pNode ) = 0;
+ virtual void Visit( SmAttributeNode* pNode ) = 0;
+ virtual void Visit( SmFontNode* pNode ) = 0;
+ virtual void Visit( SmUnHorNode* pNode ) = 0;
+ virtual void Visit( SmBinHorNode* pNode ) = 0;
+ virtual void Visit( SmBinVerNode* pNode ) = 0;
+ virtual void Visit( SmBinDiagonalNode* pNode ) = 0;
+ virtual void Visit( SmSubSupNode* pNode ) = 0;
+ virtual void Visit( SmMatrixNode* pNode ) = 0;
+ virtual void Visit( SmPlaceNode* pNode ) = 0;
+ virtual void Visit( SmTextNode* pNode ) = 0;
+ virtual void Visit( SmSpecialNode* pNode ) = 0;
+ virtual void Visit( SmGlyphSpecialNode* pNode ) = 0;
+ virtual void Visit( SmMathSymbolNode* pNode ) = 0;
+ virtual void Visit( SmBlankNode* pNode ) = 0;
+ virtual void Visit( SmErrorNode* pNode ) = 0;
+ virtual void Visit( SmLineNode* pNode ) = 0;
+ virtual void Visit( SmExpressionNode* pNode ) = 0;
+ virtual void Visit( SmPolyLineNode* pNode ) = 0;
+ virtual void Visit( SmRootNode* pNode ) = 0;
+ virtual void Visit( SmRootSymbolNode* pNode ) = 0;
+ virtual void Visit( SmRectangleNode* pNode ) = 0;
+ virtual void Visit( SmVerticalBraceNode* pNode ) = 0;
+
+protected:
+ ~SmVisitor() {}
+};
+
+// SmDefaultingVisitor
+
+
+/** Visitor that uses DefaultVisit for handling visits by default
+ *
+ * This abstract baseclass is useful for visitors where many methods share the same
+ * implementation.
+ */
+class SmDefaultingVisitor : public SmVisitor
+{
+public:
+ void Visit( SmTableNode* pNode ) override;
+ void Visit( SmBraceNode* pNode ) override;
+ void Visit( SmBracebodyNode* pNode ) override;
+ void Visit( SmOperNode* pNode ) override;
+ void Visit( SmAlignNode* pNode ) override;
+ void Visit( SmAttributeNode* pNode ) override;
+ void Visit( SmFontNode* pNode ) override;
+ void Visit( SmUnHorNode* pNode ) override;
+ void Visit( SmBinHorNode* pNode ) override;
+ void Visit( SmBinVerNode* pNode ) override;
+ void Visit( SmBinDiagonalNode* pNode ) override;
+ void Visit( SmSubSupNode* pNode ) override;
+ void Visit( SmMatrixNode* pNode ) override;
+ void Visit( SmPlaceNode* pNode ) override;
+ void Visit( SmTextNode* pNode ) override;
+ void Visit( SmSpecialNode* pNode ) override;
+ void Visit( SmGlyphSpecialNode* pNode ) override;
+ void Visit( SmMathSymbolNode* pNode ) override;
+ void Visit( SmBlankNode* pNode ) override;
+ void Visit( SmErrorNode* pNode ) override;
+ void Visit( SmLineNode* pNode ) override;
+ void Visit( SmExpressionNode* pNode ) override;
+ void Visit( SmPolyLineNode* pNode ) override;
+ void Visit( SmRootNode* pNode ) override;
+ void Visit( SmRootSymbolNode* pNode ) override;
+ void Visit( SmRectangleNode* pNode ) override;
+ void Visit( SmVerticalBraceNode* pNode ) override;
+protected:
+ ~SmDefaultingVisitor() {}
+
+ /** Method invoked by Visit methods by default */
+ virtual void DefaultVisit( SmNode* pNode ) = 0;
+};
+
+// SmCaretLinesVisitor: ancestor of caret rectangle enumeration and drawing visitors
+
+class SmCaretLinesVisitor : public SmDefaultingVisitor
+{
+public:
+ SmCaretLinesVisitor(OutputDevice& rDevice, SmCaretPos position, Point offset);
+ virtual ~SmCaretLinesVisitor() = default;
+ void Visit(SmTextNode* pNode) override;
+ using SmDefaultingVisitor::Visit;
+
+protected:
+ void DoIt();
+
+ OutputDevice& getDev() { return mrDev; }
+ virtual void ProcessCaretLine(Point from, Point to) = 0;
+ virtual void ProcessUnderline(Point from, Point to) = 0;
+
+ /** Default method for drawing pNodes */
+ void DefaultVisit(SmNode* pNode) override;
+
+private:
+ OutputDevice& mrDev;
+ SmCaretPos maPos;
+ /** Offset to draw from */
+ Point maOffset;
+};
+
+// SmCaretRectanglesVisitor: obtains the set of rectangles to sent to lok
+
+class SmCaretRectanglesVisitor final : public SmCaretLinesVisitor
+{
+public:
+ SmCaretRectanglesVisitor(OutputDevice& rDevice, SmCaretPos position);
+ const tools::Rectangle& getCaret() const { return maCaret; }
+
+protected:
+ virtual void ProcessCaretLine(Point from, Point to) override;
+ virtual void ProcessUnderline(Point from, Point to) override;
+
+private:
+ tools::Rectangle maCaret;
+};
+
+// SmCaretDrawingVisitor
+
+/** Visitor for drawing a caret position */
+class SmCaretDrawingVisitor final : public SmCaretLinesVisitor
+{
+public:
+ /** Given position and device this constructor will draw the caret */
+ SmCaretDrawingVisitor( OutputDevice& rDevice, SmCaretPos position, Point offset, bool caretVisible );
+
+protected:
+ virtual void ProcessCaretLine(Point from, Point to) override;
+ virtual void ProcessUnderline(Point from, Point to) override;
+
+private:
+ bool mbCaretVisible;
+};
+
+// SmCaretPos2LineVisitor
+
+/** Visitor getting a line from a caret position */
+class SmCaretPos2LineVisitor final : public SmDefaultingVisitor
+{
+public:
+ /** Given position and device this constructor will compute a line for the caret */
+ SmCaretPos2LineVisitor( OutputDevice *pDevice, SmCaretPos position )
+ : mpDev( pDevice )
+ , maPos( position )
+ {
+ SAL_WARN_IF( !position.IsValid(), "starmath", "Cannot draw invalid position!" );
+
+ maPos.pSelectedNode->Accept( this );
+ }
+ virtual ~SmCaretPos2LineVisitor() {}
+ void Visit( SmTextNode* pNode ) override;
+ using SmDefaultingVisitor::Visit;
+ const SmCaretLine& GetResult( ) const {
+ return maLine;
+ }
+private:
+ SmCaretLine maLine;
+ VclPtr<OutputDevice> mpDev;
+ SmCaretPos maPos;
+
+ /** Default method for computing lines for pNodes */
+ void DefaultVisit( SmNode* pNode ) override;
+};
+
+// SmDrawingVisitor
+
+/** Visitor for drawing SmNodes to OutputDevice */
+class SmDrawingVisitor final : public SmVisitor
+{
+public:
+ /** Create an instance of SmDrawingVisitor, and use it to draw a formula
+ * @param rDevice Device to draw on
+ * @param position Offset on device to draw the formula
+ * @param pTree Formula tree to draw
+ * @param rFormat Formula formatting settings
+ * @remarks This constructor will do the drawing, no need to anything more.
+ */
+ SmDrawingVisitor( OutputDevice &rDevice, Point position, SmNode* pTree, const SmFormat& rFormat )
+ : mrDev( rDevice )
+ , maPosition( position )
+ , mrFormat( rFormat )
+ {
+ if (mrFormat.IsRightToLeft() && mrDev.GetOutDevType() != OUTDEV_WINDOW)
+ mrDev.ReMirror(maPosition);
+ pTree->Accept( this );
+ }
+ virtual ~SmDrawingVisitor() {}
+ void Visit( SmTableNode* pNode ) override;
+ void Visit( SmBraceNode* pNode ) override;
+ void Visit( SmBracebodyNode* pNode ) override;
+ void Visit( SmOperNode* pNode ) override;
+ void Visit( SmAlignNode* pNode ) override;
+ void Visit( SmAttributeNode* pNode ) override;
+ void Visit( SmFontNode* pNode ) override;
+ void Visit( SmUnHorNode* pNode ) override;
+ void Visit( SmBinHorNode* pNode ) override;
+ void Visit( SmBinVerNode* pNode ) override;
+ void Visit( SmBinDiagonalNode* pNode ) override;
+ void Visit( SmSubSupNode* pNode ) override;
+ void Visit( SmMatrixNode* pNode ) override;
+ void Visit( SmPlaceNode* pNode ) override;
+ void Visit( SmTextNode* pNode ) override;
+ void Visit( SmSpecialNode* pNode ) override;
+ void Visit( SmGlyphSpecialNode* pNode ) override;
+ void Visit( SmMathSymbolNode* pNode ) override;
+ void Visit( SmBlankNode* pNode ) override;
+ void Visit( SmErrorNode* pNode ) override;
+ void Visit( SmLineNode* pNode ) override;
+ void Visit( SmExpressionNode* pNode ) override;
+ void Visit( SmPolyLineNode* pNode ) override;
+ void Visit( SmRootNode* pNode ) override;
+ void Visit( SmRootSymbolNode* pNode ) override;
+ void Visit( SmRectangleNode* pNode ) override;
+ void Visit( SmVerticalBraceNode* pNode ) override;
+private:
+ /** Draw the children of a pNode
+ * This the default method, use by most pNodes
+ */
+ void DrawChildren( SmStructureNode* pNode );
+
+ /** Draw an SmTextNode or a subclass of this */
+ void DrawTextNode( SmTextNode* pNode );
+ /** Draw an SmSpecialNode or a subclass of this */
+ void DrawSpecialNode( SmSpecialNode* pNode );
+ /** OutputDevice to draw on */
+ OutputDevice& mrDev;
+ /** Position to draw on the mrDev
+ * @remarks This variable is used to pass parameters in DrawChildren( ), this means
+ that after a call to DrawChildren( ) the contents of this method is undefined
+ so if needed cache it locally on the stack.
+ */
+ Point maPosition;
+ const SmFormat& mrFormat;
+};
+
+// SmSetSelectionVisitor
+
+/** Set Selection Visitor
+ * Sets the IsSelected( ) property on all SmNodes of the tree
+ */
+class SmSetSelectionVisitor final : public SmDefaultingVisitor
+{
+public:
+ SmSetSelectionVisitor( SmCaretPos startPos, SmCaretPos endPos, SmNode* pNode);
+ virtual ~SmSetSelectionVisitor() {}
+ void Visit( SmBinHorNode* pNode ) override;
+ void Visit( SmUnHorNode* pNode ) override;
+ void Visit( SmFontNode* pNode ) override;
+ void Visit( SmTextNode* pNode ) override;
+ void Visit( SmExpressionNode* pNode ) override;
+ void Visit( SmLineNode* pNode ) override;
+ void Visit( SmAlignNode* pNode ) override;
+ using SmDefaultingVisitor::Visit;
+ /** Set IsSelected on all pNodes of pSubTree */
+ static void SetSelectedOnAll( SmNode* pSubTree, bool IsSelected = true );
+private:
+ /** Visit a selectable pNode
+ * Can be used to handle pNodes that can be selected, that doesn't have more SmCaretPos'
+ * than 0 and 1 inside them. SmTextNode should be handle separately!
+ * Also note that pNodes such as SmBinVerNode cannot be selected, don't this method for
+ * it.
+ */
+ void DefaultVisit( SmNode* pNode ) override;
+ void VisitCompositionNode( SmStructureNode* pNode );
+ /** Caret position where the selection starts */
+ SmCaretPos maStartPos;
+ /** Caret position where the selection ends */
+ SmCaretPos maEndPos;
+ /** The current state of this visitor
+ * This property changes when the visitor meets either maStartPos
+ * or maEndPos. This means that anything visited in between will be
+ * selected.
+ */
+ bool mbSelecting;
+};
+
+
+// SmCaretPosGraphBuildingVisitor
+
+
+/** A visitor for building a SmCaretPosGraph
+ *
+ * Visit invariant:
+ * Each pNode, except SmExpressionNode, SmBinHorNode and a few others, constitutes an entry
+ * in a line. Consider the line entry "H", this entry creates one carat position, here
+ * denoted by | in "H|".
+ *
+ * Parameter variables:
+ * The following variables are used to transfer parameters into calls and results out
+ * of calls.
+ * pRightMost : SmCaretPosGraphEntry*
+ *
+ * Prior to a Visit call:
+ * pRightMost: A pointer to right most position in front of the current line entry.
+ *
+ * After a Visit call:
+ * pRightMost: A pointer to the right most position in the called line entry, if no there's
+ * no caret positions in called line entry don't change this variable.
+ */
+class SmCaretPosGraphBuildingVisitor final : public SmVisitor
+{
+public:
+ /** Builds a caret position graph for pRootNode */
+ explicit SmCaretPosGraphBuildingVisitor( SmNode* pRootNode );
+ virtual ~SmCaretPosGraphBuildingVisitor();
+ void Visit( SmTableNode* pNode ) override;
+ void Visit( SmBraceNode* pNode ) override;
+ void Visit( SmBracebodyNode* pNode ) override;
+ void Visit( SmOperNode* pNode ) override;
+ void Visit( SmAlignNode* pNode ) override;
+ void Visit( SmAttributeNode* pNode ) override;
+ void Visit( SmFontNode* pNode ) override;
+ void Visit( SmUnHorNode* pNode ) override;
+ void Visit( SmBinHorNode* pNode ) override;
+ void Visit( SmBinVerNode* pNode ) override;
+ void Visit( SmBinDiagonalNode* pNode ) override;
+ void Visit( SmSubSupNode* pNode ) override;
+ void Visit( SmMatrixNode* pNode ) override;
+ void Visit( SmPlaceNode* pNode ) override;
+ void Visit( SmTextNode* pNode ) override;
+ void Visit( SmSpecialNode* pNode ) override;
+ void Visit( SmGlyphSpecialNode* pNode ) override;
+ void Visit( SmMathSymbolNode* pNode ) override;
+ void Visit( SmBlankNode* pNode ) override;
+ void Visit( SmErrorNode* pNode ) override;
+ void Visit( SmLineNode* pNode ) override;
+ void Visit( SmExpressionNode* pNode ) override;
+ void Visit( SmPolyLineNode* pNode ) override;
+ void Visit( SmRootNode* pNode ) override;
+ void Visit( SmRootSymbolNode* pNode ) override;
+ void Visit( SmRectangleNode* pNode ) override;
+ void Visit( SmVerticalBraceNode* pNode ) override;
+ SmCaretPosGraph* takeGraph()
+ {
+ return mpGraph.release();
+ }
+private:
+ SmCaretPosGraphEntry* mpRightMost;
+ std::unique_ptr<SmCaretPosGraph> mpGraph;
+};
+
+// SmCloningVisitor
+
+/** Visitor for cloning a pNode
+ *
+ * This visitor creates deep clones.
+ */
+class SmCloningVisitor final : public SmVisitor
+{
+public:
+ SmCloningVisitor()
+ : mpResult(nullptr)
+ {}
+ virtual ~SmCloningVisitor() {}
+ void Visit( SmTableNode* pNode ) override;
+ void Visit( SmBraceNode* pNode ) override;
+ void Visit( SmBracebodyNode* pNode ) override;
+ void Visit( SmOperNode* pNode ) override;
+ void Visit( SmAlignNode* pNode ) override;
+ void Visit( SmAttributeNode* pNode ) override;
+ void Visit( SmFontNode* pNode ) override;
+ void Visit( SmUnHorNode* pNode ) override;
+ void Visit( SmBinHorNode* pNode ) override;
+ void Visit( SmBinVerNode* pNode ) override;
+ void Visit( SmBinDiagonalNode* pNode ) override;
+ void Visit( SmSubSupNode* pNode ) override;
+ void Visit( SmMatrixNode* pNode ) override;
+ void Visit( SmPlaceNode* pNode ) override;
+ void Visit( SmTextNode* pNode ) override;
+ void Visit( SmSpecialNode* pNode ) override;
+ void Visit( SmGlyphSpecialNode* pNode ) override;
+ void Visit( SmMathSymbolNode* pNode ) override;
+ void Visit( SmBlankNode* pNode ) override;
+ void Visit( SmErrorNode* pNode ) override;
+ void Visit( SmLineNode* pNode ) override;
+ void Visit( SmExpressionNode* pNode ) override;
+ void Visit( SmPolyLineNode* pNode ) override;
+ void Visit( SmRootNode* pNode ) override;
+ void Visit( SmRootSymbolNode* pNode ) override;
+ void Visit( SmRectangleNode* pNode ) override;
+ void Visit( SmVerticalBraceNode* pNode ) override;
+ /** Clone a pNode */
+ SmNode* Clone( SmNode* pNode );
+private:
+ SmNode* mpResult;
+ /** Clone children of pSource and give them to pTarget */
+ void CloneKids( SmStructureNode* pSource, SmStructureNode* pTarget );
+ /** Clone attributes on a pNode */
+ static void CloneNodeAttr( SmNode const * pSource, SmNode* pTarget );
+};
+
+
+// SmSelectionRectanglesVisitor: collect selection
+
+class SmSelectionRectanglesVisitor : public SmDefaultingVisitor
+{
+public:
+ SmSelectionRectanglesVisitor(OutputDevice& rDevice, SmNode* pTree);
+ virtual ~SmSelectionRectanglesVisitor() = default;
+ void Visit( SmTextNode* pNode ) override;
+ using SmDefaultingVisitor::Visit;
+
+ const tools::Rectangle& GetSelection() { return maSelectionArea; }
+
+private:
+ /** Reference to drawing device */
+ OutputDevice& mrDev;
+ /** The current area that is selected */
+ tools::Rectangle maSelectionArea;
+ /** Extend the area that must be selected */
+ void ExtendSelectionArea(const tools::Rectangle& rArea) { maSelectionArea.Union(rArea); }
+ /** Default visiting method */
+ void DefaultVisit( SmNode* pNode ) override;
+ /** Visit the children of a given pNode */
+ void VisitChildren( SmNode* pNode );
+};
+
+// SmSelectionDrawingVisitor
+
+class SmSelectionDrawingVisitor final : public SmSelectionRectanglesVisitor
+{
+public:
+ /** Draws a selection on rDevice for the selection on pTree */
+ SmSelectionDrawingVisitor( OutputDevice& rDevice, SmNode* pTree, const Point& rOffset );
+};
+
+// SmNodeToTextVisitor
+
+/** Extract command text from pNodes */
+class SmNodeToTextVisitor final : public SmVisitor
+{
+public:
+ SmNodeToTextVisitor( SmNode* pNode, OUString &rText );
+ virtual ~SmNodeToTextVisitor() {}
+
+ void Visit( SmTableNode* pNode ) override;
+ void Visit( SmBraceNode* pNode ) override;
+ void Visit( SmBracebodyNode* pNode ) override;
+ void Visit( SmOperNode* pNode ) override;
+ void Visit( SmAlignNode* pNode ) override;
+ void Visit( SmAttributeNode* pNode ) override;
+ void Visit( SmFontNode* pNode ) override;
+ void Visit( SmUnHorNode* pNode ) override;
+ void Visit( SmBinHorNode* pNode ) override;
+ void Visit( SmBinVerNode* pNode ) override;
+ void Visit( SmBinDiagonalNode* pNode ) override;
+ void Visit( SmSubSupNode* pNode ) override;
+ void Visit( SmMatrixNode* pNode ) override;
+ void Visit( SmPlaceNode* pNode ) override;
+ void Visit( SmTextNode* pNode ) override;
+ void Visit( SmSpecialNode* pNode ) override;
+ void Visit( SmGlyphSpecialNode* pNode ) override;
+ void Visit( SmMathSymbolNode* pNode ) override;
+ void Visit( SmBlankNode* pNode ) override;
+ void Visit( SmErrorNode* pNode ) override;
+ void Visit( SmLineNode* pNode ) override;
+ void Visit( SmExpressionNode* pNode ) override;
+ void Visit( SmPolyLineNode* pNode ) override;
+ void Visit( SmRootNode* pNode ) override;
+ void Visit( SmRootSymbolNode* pNode ) override;
+ void Visit( SmRectangleNode* pNode ) override;
+ void Visit( SmVerticalBraceNode* pNode ) override;
+private:
+
+ /**
+ * Extract text from a pNode that constitutes a line.
+ * @param pNode
+ * @return
+ */
+ void LineToText( SmNode* pNode ) {
+ Separate( );
+ if( pNode ) pNode->Accept( this );
+ Separate( );
+ }
+
+ /**
+ * Appends rText to the OUStringBuffer ( maCmdText ).
+ * @param rText
+ * @return
+ */
+ void Append( std::u16string_view rText ) {
+ maCmdText.append( rText );
+ }
+
+ /**
+ * Append a blank for separation, if needed.
+ * It is needed if last char is not ' '.
+ * @return
+ */
+ void Separate( ){
+ if( !maCmdText.isEmpty() && maCmdText[ maCmdText.getLength() - 1 ] != ' ' )
+ maCmdText.append(' ');
+ }
+
+ /** Output text generated from the pNodes */
+ OUStringBuffer maCmdText;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */