fdo#53472 Created Dynamic Integral Node classes. Integrals size made dependent on body.

Change-Id: I0348155f2429cf7dd3cbe7d71f333879ec6de980
Reviewed-on: https://gerrit.libreoffice.org/8569
Reviewed-by: Norbert Thiebaud <nthiebaud@gmail.com>
Tested-by: Norbert Thiebaud <nthiebaud@gmail.com>
This commit is contained in:
matteocam
2014-02-25 14:37:55 -05:00
committed by Norbert Thiebaud
parent edc8ee0099
commit 93e6291c29
10 changed files with 297 additions and 4 deletions

View File

@@ -73,7 +73,7 @@ enum SmNodeType
/*10*/ NBINDIAGONAL, NSUBSUP, NMATRIX, NPLACE, NTEXT,
/*15*/ NSPECIAL, NGLYPH_SPECIAL, NMATH, NBLANK, NERROR,
/*20*/ NLINE, NEXPRESSION, NPOLYLINE, NROOT, NROOTSYMBOL,
/*25*/ NRECTANGLE, NVERTICAL_BRACE, NMATHIDENT
/*25*/ NRECTANGLE, NVERTICAL_BRACE, NMATHIDENT, NDYNINT, NDYNINTSYMBOL
};
@@ -618,6 +618,30 @@ public:
void Accept(SmVisitor* pVisitor);
};
////////////////////////////////////////////////////////////////////////////////
/** Dynamic Integral symbol node
*
* Node for drawing dynamicall sized integral symbols.
*
* TODO: It might be created a parent class SmDynamicSizedNode
(for both dynamic integrals, roots and other dynamic symbols)
*/
class SmDynIntegralSymbolNode : public SmMathSymbolNode
{
public:
SmDynIntegralSymbolNode(const SmToken &rNodeToken)
: SmMathSymbolNode(NDYNINTSYMBOL, rNodeToken)
{}
virtual void AdaptToY(const OutputDevice &rDev, sal_uLong nHeight);
void Accept(SmVisitor* pVisitor);
};
@@ -806,6 +830,40 @@ public:
};
////////////////////////////////////////////////////////////////////////////////
/** Dynamic Integral node
*
* Used to create Dynamically sized integrals
*
* Children:<BR>
* 0: Symbol (instance of DynIntegralSymbolNode)<BR>
* 1: Body<BR>
*/
class SmDynIntegralNode : public SmStructureNode
{
protected:
void GetHeightVerOffset(const SmRect &rRect,
long &rHeight, long &rVerOffset) const;
public:
SmDynIntegralNode(const SmToken &rNodeToken)
: SmStructureNode(NDYNINT, rNodeToken)
{
SetNumSubNodes(2);
}
virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
void CreateTextFromNode(OUString &rText);
void Accept(SmVisitor* pVisitor);
SmDynIntegralSymbolNode* Symbol();
const SmDynIntegralSymbolNode* Symbol() const;
SmNode* Body();
const SmNode* Body() const;
};
/** Binary horizontial node
@@ -1293,6 +1351,28 @@ inline const SmNode* SmRootNode::Body() const
return const_cast< SmRootNode* >( this )->Body();
}
inline SmDynIntegralSymbolNode* SmDynIntegralNode::Symbol()
{
OSL_ASSERT( GetNumSubNodes() > 0 && GetSubNode( 0 )->GetType() == NDYNINTSYMBOL );
return static_cast< SmDynIntegralSymbolNode* >( GetSubNode( 0 ));
}
inline const SmDynIntegralSymbolNode* SmDynIntegralNode::Symbol() const
{
return const_cast< SmDynIntegralNode* >( this )->Symbol();
}
inline SmNode* SmDynIntegralNode::Body()
{
OSL_ASSERT( GetNumSubNodes() > 1 );
return GetSubNode( 1 );
}
inline const SmNode* SmDynIntegralNode::Body() const
{
return const_cast< SmDynIntegralNode* >( this )->Body();
}
inline SmMathSymbolNode* SmBinHorNode::Symbol()
{
OSL_ASSERT( GetNumSubNodes() > 1 && GetSubNode( 1 )->GetType() == NMATH );

View File

@@ -102,7 +102,8 @@ enum SmTokenType
/*215*/ TSETR, TSETC, TWIDEVEC, TWIDETILDE, TWIDEHAT,
/*220*/ TWIDESLASH, TWIDEBACKSLASH, TLDBRACKET, TRDBRACKET, TNOSPACE,
/*225*/ TUNKNOWN, TDEBUG, TPRECEDES, TSUCCEEDS, TPRECEDESEQUAL,
/*230*/ TSUCCEEDSEQUAL, TPRECEDESEQUIV, TSUCCEEDSEQUIV, TNOTPRECEDES, TNOTSUCCEEDS
/*230*/ TSUCCEEDSEQUAL, TPRECEDESEQUIV, TSUCCEEDSEQUIV, TNOTPRECEDES, TNOTSUCCEEDS,
/*235*/ TINTD
};

View File

@@ -42,6 +42,8 @@ public:
virtual void Visit( SmLineNode* pNode ) = 0;
virtual void Visit( SmExpressionNode* pNode ) = 0;
virtual void Visit( SmPolyLineNode* pNode ) = 0;
virtual void Visit( SmDynIntegralNode* pNode ) = 0;
virtual void Visit( SmDynIntegralSymbolNode* pNode ) = 0;
virtual void Visit( SmRootNode* pNode ) = 0;
virtual void Visit( SmRootSymbolNode* pNode ) = 0;
virtual void Visit( SmRectangleNode* pNode ) = 0;
@@ -81,6 +83,8 @@ public:
void Visit( SmPolyLineNode* pNode );
void Visit( SmRootNode* pNode );
void Visit( SmRootSymbolNode* pNode );
void Visit( SmDynIntegralNode* pNode );
void Visit( SmDynIntegralSymbolNode* pNode );
void Visit( SmRectangleNode* pNode );
void Visit( SmVerticalBraceNode* pNode );
private:
@@ -124,6 +128,8 @@ public:
void Visit( SmPolyLineNode* pNode );
void Visit( SmRootNode* pNode );
void Visit( SmRootSymbolNode* pNode );
void Visit( SmDynIntegralNode* pNode );
void Visit( SmDynIntegralSymbolNode* pNode );
void Visit( SmRectangleNode* pNode );
void Visit( SmVerticalBraceNode* pNode );
protected:
@@ -227,6 +233,8 @@ public:
void Visit( SmPolyLineNode* pNode );
void Visit( SmRootNode* pNode );
void Visit( SmRootSymbolNode* pNode );
void Visit( SmDynIntegralNode* pNode );
void Visit( SmDynIntegralSymbolNode* pNode );
void Visit( SmRectangleNode* pNode );
void Visit( SmVerticalBraceNode* pNode );
private:
@@ -344,6 +352,8 @@ public:
void Visit( SmPolyLineNode* pNode );
void Visit( SmRootNode* pNode );
void Visit( SmRootSymbolNode* pNode );
void Visit( SmDynIntegralNode* pNode );
void Visit( SmDynIntegralSymbolNode* pNode );
void Visit( SmRectangleNode* pNode );
void Visit( SmVerticalBraceNode* pNode );
SmCaretPosGraph* takeGraph()
@@ -393,6 +403,8 @@ public:
void Visit( SmPolyLineNode* pNode );
void Visit( SmRootNode* pNode );
void Visit( SmRootSymbolNode* pNode );
void Visit( SmDynIntegralNode* pNode );
void Visit( SmDynIntegralSymbolNode* pNode );
void Visit( SmRectangleNode* pNode );
void Visit( SmVerticalBraceNode* pNode );
/** Clone a pNode */
@@ -465,6 +477,8 @@ public:
void Visit( SmPolyLineNode* pNode );
void Visit( SmRootNode* pNode );
void Visit( SmRootSymbolNode* pNode );
void Visit( SmDynIntegralNode* pNode );
void Visit( SmDynIntegralSymbolNode* pNode );
void Visit( SmRectangleNode* pNode );
void Visit( SmVerticalBraceNode* pNode );
private:

View File

@@ -2516,6 +2516,7 @@ void MathType::HandleOperator(SmNode *pNode,int nLevel)
switch(pNode->GetToken().eType)
{
case TINT:
case TINTD:
if (nOldVariation != 0xff)
pS->WriteUChar( sal_uInt8(0x18) ); //selector
else
@@ -2640,6 +2641,7 @@ void MathType::HandleOperator(SmNode *pNode,int nLevel)
pS->WriteUChar( sal_uInt8(0x86) );
pS->WriteUInt16( sal_uInt16(0x222B) );
case TINT:
case TINTD:
case TLINT:
pS->WriteUChar( sal_uInt8(CHAR) );
pS->WriteUChar( sal_uInt8(0x86) );

View File

@@ -197,7 +197,7 @@ private:
tmANGLE,tmPAREN,tmBRACE,tmBRACK,tmBAR,tmDBAR,tmFLOOR,tmCEILING,
tmLBLB,tmRBRB,tmRBLB,tmLBRP,tmLPRB,tmROOT,tmFRACT,tmSCRIPT,tmUBAR,
tmOBAR,tmLARROW,tmRARROW,tmBARROW,tmSINT,tmDINT,tmTINT,tmSSINT,
tmDSINT,tmTSINT,tmUHBRACE,tmLHBRACE,tmSUM
tmDSINT,tmTSINT,tmUHBRACE,tmLHBRACE,tmSUM,tmTINTD
};
public:
static sal_Bool LookupChar(sal_Unicode nChar,OUString &rRet,

View File

@@ -622,6 +622,8 @@ void SmNode::DumpAsDot(std::ostream &out, OUString* label, int number, int& id,
case NRECTANGLE: out<<"SmRectangleNode"; break;
case NVERTICAL_BRACE: out<<"SmVerticalBraceNode"; break;
case NMATHIDENT: out<<"SmMathIdentifierNode"; break;
case NINTDYNSYMBOL: out<<"SmDynIntegralSymbolNode"; break;
case NINTDYN: out<<"SmDynIntegralNode"; break;
default:
out<<"Unknown Node";
}
@@ -1115,6 +1117,53 @@ void SmRootNode::CreateTextFromNode(OUString &rText)
rText += "} ";
}
/**************************************************************************/
void SmDynIntegralNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat)
{
SmNode *pDynIntegralSym = Symbol(),
*pBody = Body();
OSL_ENSURE(pDynIntegralSym, "Sm: NULL pointer");
OSL_ENSURE(pBody, "Sm: NULL pointer");
pBody->Arrange(rDev, rFormat);
long nHeight = pBody->GetHeight();
pDynIntegralSym->AdaptToY(rDev, nHeight);
pDynIntegralSym->Arrange(rDev, rFormat);
Point aPos = pDynIntegralSym->AlignTo(*pBody, RP_LEFT, RHA_CENTER, RVA_BASELINE);
//! override calculated vertical position
aPos.Y() = pDynIntegralSym->GetTop() + pBody->GetBottom() - pDynIntegralSym->GetBottom();
pDynIntegralSym->MoveTo(aPos);
// override its own rectangle with pBody's
SmRect::operator = (*pBody);
// extends this rectangle with the symbol's one
ExtendBy(*pDynIntegralSym, RCP_THIS);
}
void SmDynIntegralNode::CreateTextFromNode(OUString &rText)
{
rText += "intd ";
SmNode *pBody = GetSubNode(1);
if (pBody->GetNumSubNodes() > 1)
rText += "{ ";
pBody->CreateTextFromNode(rText);
if (pBody->GetNumSubNodes() > 1)
rText += "} ";
}
/**************************************************************************/
@@ -2297,6 +2346,23 @@ void SmRootSymbolNode::AdaptToY(const OutputDevice &rDev, sal_uLong nHeight)
/**************************************************************************/
void SmDynIntegralSymbolNode::AdaptToY(const OutputDevice &rDev, sal_uLong nHeight)
{
long nFactor = 12L;
// The new height equals (1 + nFactor) * oldHeight
// nFactor was chosen for keeping the integral sign from becoming too "fat".
SmMathSymbolNode::AdaptToY(rDev, nHeight + nHeight / nFactor);
// keep the ratio
long nCurWidth = GetSize().Width();
SmMathSymbolNode::AdaptToX(rDev, nCurWidth + nCurWidth / nFactor);
}
/**************************************************************************/
void SmRectangleNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nWidth)
{
aToSize.Width() = nWidth;
@@ -3196,6 +3262,15 @@ void SmRootSymbolNode::Accept(SmVisitor* pVisitor) {
pVisitor->Visit(this);
}
void SmDynIntegralNode::Accept(SmVisitor* pVisitor) {
pVisitor->Visit(this);
}
void SmDynIntegralSymbolNode::Accept(SmVisitor* pVisitor) {
pVisitor->Visit(this);
}
void SmRectangleNode::Accept(SmVisitor* pVisitor) {
pVisitor->Visit(this);
}

View File

@@ -249,6 +249,7 @@ void SmOoxmlExport::HandleOperator( const SmOperNode* pNode, int nLevel )
switch( pNode->GetToken().eType )
{
case TINT:
case TINTD:
case TIINT:
case TIIINT:
case TLINT:

View File

@@ -161,6 +161,7 @@ static const SmTokenTableEntry aTokenTable[] =
{ "infinity" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5},
{ "infty" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5},
{ "int", TINT, MS_INT, TGOPER, 5},
{ "intd", TINTD, MS_INT, TGUNOPER, 5},
{ "intersection", TINTERSECT, MS_INTERSECT, TGPRODUCT, 0},
{ "ital", TITALIC, '\0', TGFONTATTR, 5},
{ "italic", TITALIC, '\0', TGFONTATTR, 5},
@@ -1689,6 +1690,10 @@ void SmParser::UnOper()
{
case TABS :
case TSQRT :
/* Dynamic integrals are handled as unary operators so we can wrap
the symbol together with the body in a upper level node and make
proper graphic arrangements */
case TINTD:
NextToken();
break;
@@ -1747,6 +1752,11 @@ void SmParser::UnOper()
pOper = new SmRootSymbolNode(aNodeToken);
pSNode->SetSubNodes(pExtra, pOper, pArg);
}
else if(eType == TINTD)
{ pSNode = new SmDynIntegralNode(aNodeToken);
pOper = new SmDynIntegralSymbolNode(aNodeToken);
pSNode->SetSubNodes(pOper, pArg);
}
else
{ pSNode = new SmUnHorNode(aNodeToken);

View File

@@ -198,6 +198,7 @@ void SmRtfExport::HandleOperator(const SmOperNode* pNode, int nLevel)
switch (pNode->GetToken().eType)
{
case TINT:
case TINTD:
case TIINT:
case TIIINT:
case TLINT:

View File

@@ -161,6 +161,18 @@ void SmVisitorTest::Visit( SmRootSymbolNode* pNode )
VisitChildren( pNode );
}
void SmVisitorTest::Visit( SmDynIntegralNode* pNode )
{
assert( pNode->GetType( ) == NDYNINT );
VisitChildren( pNode );
}
void SmVisitorTest::Visit( SmDynIntegralSymbolNode* pNode )
{
assert( pNode->GetType( ) == NDYNINTSYMBOL );
VisitChildren( pNode );
}
void SmVisitorTest::Visit( SmRectangleNode* pNode )
{
assert( pNode->GetType( ) == NRECTANGLE );
@@ -307,6 +319,16 @@ void SmDefaultingVisitor::Visit( SmRootSymbolNode* pNode )
DefaultVisit( pNode );
}
void SmDefaultingVisitor::Visit( SmDynIntegralNode* pNode )
{
DefaultVisit( pNode );
}
void SmDefaultingVisitor::Visit( SmDynIntegralSymbolNode* pNode )
{
DefaultVisit( pNode );
}
void SmDefaultingVisitor::Visit( SmRectangleNode* pNode )
{
DefaultVisit( pNode );
@@ -630,6 +652,11 @@ void SmDrawingVisitor::Visit( SmRootNode* pNode )
DrawChildren( pNode );
}
void SmDrawingVisitor::Visit(SmDynIntegralNode* pNode)
{
DrawChildren( pNode );
}
void SmDrawingVisitor::Visit( SmVerticalBraceNode* pNode )
{
DrawChildren( pNode );
@@ -668,6 +695,22 @@ void SmDrawingVisitor::Visit( SmRootSymbolNode* pNode )
rDev.DrawRect( aBar );
}
void SmDrawingVisitor::Visit( SmDynIntegralSymbolNode* pNode )
{
if ( pNode->IsPhantom( ) )
return;
// draw integral-sign itself
DrawSpecialNode( pNode );
//! the rest of this may not be needed at all
// this should be something like:
// instead of just drawing the node, take some information about the body.
// This is also how SmRootSymbol does it (probably by means of SmRootNode)
// NEXT: Check out SmRootNode
}
void SmDrawingVisitor::Visit( SmPolyLineNode* pNode )
{
if ( pNode->IsPhantom( ) )
@@ -1630,6 +1673,40 @@ void SmCaretPosGraphBuildingVisitor::Visit( SmRootNode* pNode )
pRightMost = right;
}
void SmCaretPosGraphBuildingVisitor::Visit( SmDynIntegralNode* pNode )
{
//! To be changed: Integrals don't have args.
SmNode *pBody = pNode->Body(); //Body of the root
SAL_WARN_IF( !pBody, "starmath", "pBody cannot be NULL" );
SmCaretPosGraphEntry *left,
*right,
*bodyLeft,
*bodyRight;
//Get left and save it
SAL_WARN_IF( !pRightMost, "starmath", "There must be a position in front of this" );
left = pRightMost;
//Create body left
bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left );
left->SetRight( bodyLeft );
//Create right
right = pGraph->Add( SmCaretPos( pNode, 1 ) );
//Visit body
pRightMost = bodyLeft;
pBody->Accept( this );
bodyRight = pRightMost;
bodyRight->SetRight( right );
right->SetLeft( bodyRight );
pRightMost = right;
}
/** Build SmCaretPosGraph for SmPlaceNode
* Consider this a single character.
*/
@@ -1772,6 +1849,13 @@ void SmCaretPosGraphBuildingVisitor::Visit( SmRootSymbolNode* )
{
//Do nothing
}
void SmCaretPosGraphBuildingVisitor::Visit( SmDynIntegralSymbolNode* )
{
//Do nothing
}
void SmCaretPosGraphBuildingVisitor::Visit( SmRectangleNode* )
{
//Do nothing
@@ -2016,6 +2100,20 @@ void SmCloningVisitor::Visit( SmRootSymbolNode* pNode )
CloneNodeAttr( pNode, pResult );
}
void SmCloningVisitor::Visit( SmDynIntegralNode* pNode )
{
SmDynIntegralNode* pClone = new SmDynIntegralNode( pNode->GetToken( ) );
CloneNodeAttr( pNode, pClone );
CloneKids( pNode, pClone );
pResult = pClone;
}
void SmCloningVisitor::Visit( SmDynIntegralSymbolNode* pNode )
{
pResult = new SmDynIntegralSymbolNode( pNode->GetToken( ) );
CloneNodeAttr( pNode, pResult );
}
void SmCloningVisitor::Visit( SmRectangleNode* pNode )
{
pResult = new SmRectangleNode( pNode->GetToken( ) );
@@ -2539,6 +2637,17 @@ void SmNodeToTextVisitor::Visit( SmRootSymbolNode* )
{
}
void SmNodeToTextVisitor::Visit( SmDynIntegralNode* pNode )
{
SmNode *pBody = pNode->Body();
Append( "intd" );
LineToText( pBody );
}
void SmNodeToTextVisitor::Visit( SmDynIntegralSymbolNode* )
{
}
void SmNodeToTextVisitor::Visit( SmRectangleNode* )
{
}