Move whole libkformula to kformula/flake. It'll become a FormulaShape and a

FormulaTool

svn path=/trunk/koffice/; revision=659143
parent 3d968c7a
......@@ -4,7 +4,6 @@ add_subdirectory( kofficecore )
add_subdirectory( kofficeui )
add_subdirectory( koproperty )
add_subdirectory( kotext )
add_subdirectory( kformula )
add_subdirectory( kopainter )
add_subdirectory( flake )
add_subdirectory( pigment )
......
Andrea Rizzi <rizzi@kde.org>
Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
Claus O. Wilke <wilke@caltech.edu>
Alfredo Beaumont <alfredo.beaumont@gmail.com>
Martin Pfeiffer <hubipete@gmx.net>
/* This file is part of the KDE project
Copyright (C) 2006 Alfredo Beaumont Sainz <alfredo.beaumont@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "ElementFactory.h"
#include "ActionElement.h"
namespace KFormula {
ActionElement::ActionElement( BasicElement* parent ) : SequenceElement( parent ),
m_selection( 0 )
{
}
void ActionElement::readMathMLAttributes(const QDomElement& element)
{
m_actionType = element.attribute( "actiontype" );
QString selectionStr = element.attribute( "selection" );
if ( ! selectionStr.isNull() ) {
bool ok;
m_selection = selectionStr.toUInt( &ok );
if ( ! ok ) m_selection = 0;
}
}
int ActionElement::buildChildrenFromMathMLDom(QList<BasicElement*>& list, QDomNode n)
{
/*
if ( ! n.isElement() )
return -1;
QDomElement e = n.toElement();
QString tag = e.tagName().lower();
BasicElement* child = getCreationStrategy()->createElement( tag, e );
if ( child == 0 )
return -1;
child->setParent( this );
if ( child->buildFromMathMLDom( e ) == -1 ) {
delete child;
return -1;
}
list.append( child );
parse();
return 1;
*/
return 0;
}
void ActionElement::writeMathMLAttributes( QDomElement& element ) const
{
if ( ! m_actionType.isNull() ) {
element.setAttribute( "actiontype", m_actionType );
}
if ( m_selection ) {
element.setAttribute( "selection", QString( "%1" ).arg( m_selection ) );
}
}
} // namespace KFormula
/* This file is part of the KDE project
Copyright (C) 2006 Alfredo Beaumont Sainz <alfredo.beaumont@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef ACTIONELEMENT_H
#define ACTIONELEMENT_H
#include "SequenceElement.h"
namespace KFormula {
/**
* Support for action elements in MathML. According to MathML spec
* (Section 3.6.1.1), a MathML conformant application is not required to
* recognize any single actiontype.
*/
class ActionElement : public SequenceElement {
public:
ActionElement( BasicElement* parent = 0 );
virtual int buildChildrenFromMathMLDom(QList<BasicElement*>& list, QDomNode n);
private:
virtual void readMathMLAttributes(const QDomElement& element);
virtual QString elementName() const { return "maction"; }
virtual void writeMathMLAttributes( QDomElement& element ) const ;
QString m_actionType;
uint m_selection;
};
} // namespace KFormula
#endif // ACTIONELEMENT_H
/* This file is part of the KDE project
Copyright (C) 2006 Martin Pfeiffer <hubipete@gmx.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "AttributeManager.h"
#include "BasicElement.h"
#include <KoUnit.h>
#include <KoViewConverter.h>
#include <KoPostscriptPaintDevice.h>
#include <QFontMetricsF>
#include <QColor>
namespace FormulaShape {
AttributeManager::AttributeManager()
{
m_viewConverter = 0;
m_scriptLevelStack.push( 0 ); // set startup scriptlevel to 0
}
AttributeManager::~AttributeManager()
{}
void AttributeManager::inheritAttributes( const BasicElement* element )
{
if( element->elementType() == Formula ) // FormulaElement has no attributes
return;
// check for the parent element and rebuild attribute heritage if needed
if( m_attributeStack.isEmpty() ||
element->parentElement() != m_attributeStack.first() )
buildHeritageOf( element );
else
{
m_attributeStack.push( element ); // add the element to the stack
alterScriptLevel( element ); // adapt the scritplevel
}
}
void AttributeManager::disinheritAttributes()
{
m_attributeStack.pop(); // remove it from stack
m_scriptLevelStack.pop();
}
QVariant AttributeManager::valueOf( const QString& attribute ) const
{
// check if the current element has a value assigned
QString value;
value = m_attributeStack.first()->attribute( attribute );
if( !value.isEmpty() )
return parseValue( value );
// if not, check if any element in the stack might inherit a value
foreach( const BasicElement* tmp, m_attributeStack )
{
value = tmp->inheritsAttribute( attribute );
if( !value.isEmpty() )
return parseValue( value );
}
// if not, return the default value of the attribute
return m_attributeStack.first()->attributesDefaultValue( attribute );
}
Align AttributeManager::alignValueOf( const QString& attribute ) const
{
QString tmpAlignValue = valueOf( attribute ).toString();
if( tmpAlignValue == "right" )
return Right;
else if( tmpAlignValue == "left" )
return Left;
else
return Center;
}
QVariant AttributeManager::parseValue( const QString& value ) const
{
// check if the value includes metric units
if( parseMetrics( value ).isValid() )
return parseMetrics( value );
// look for attributes that are enums
if( mathVariantValue( value ) != -1 )
return mathVariantValue( value );
else if( mathSpaceValue( value ) != -1.0)
return mathSpaceValue( value );
else if( formValue( value ) != -1 )
return formValue( value );
// look if the value is color
QColor tmpColor( value );
if( tmpColor.isValid() )
return tmpColor;
// all other values don't need special treatment
return QVariant( value );
}
void AttributeManager::buildHeritageOf( const BasicElement* element )
{
m_attributeStack.clear();
m_scriptLevelStack.clear();
m_scriptLevelStack.push( 0 ); // see 3.3.4.2 of the MathML spec
const BasicElement* tmpElement = element;
while( tmpElement )
{
m_attributeStack.push( tmpElement );
alterScriptLevel( tmpElement );
tmpElement = tmpElement->parentElement();
}
}
void AttributeManager::alterScriptLevel( const BasicElement* element )
{
// set the scriptlevel explicitly
QString value = element->attribute( "scriptlevel" );
if( !value.isEmpty() )
{
// catch increments or decrements that may only affect scriptlevel
if( value.startsWith( "+" ) )
{
int tmp = m_scriptLevelStack.top() + value.remove( 0, 1 ).toInt();
m_scriptLevelStack.push( tmp );
}
else if( value.startsWith( "-" ) )
{
int tmp = m_scriptLevelStack.top() - value.remove( 0, 1 ).toInt();
m_scriptLevelStack.push( tmp );
}
else
m_scriptLevelStack.push( value.toInt() );
}
else if( element->parentElement()->elementType() == MultiScript ||
element->parentElement()->elementType() == UnderOver )
m_scriptLevelStack.push( m_scriptLevelStack.top()++ );
else if( element->parentElement()->elementType() == Fraction &&
valueOf( "displaystyle" ).toBool() )
m_scriptLevelStack.push( m_scriptLevelStack.top()++ );
else if( element->parentElement()->elementType() == Root &&
element == element->parentElement()->childElements().value( 1 ) )
m_scriptLevelStack.push( m_scriptLevelStack.top()+2 ); // only for roots index
else
m_scriptLevelStack.push( m_scriptLevelStack.top() );
}
int AttributeManager::formValue( const QString& value ) const
{
if( value == "prefix" )
return Prefix;
else if( value == "infix" )
return Infix;
else if( value == "postfix" )
return Postfix;
else
return -1;
}
int AttributeManager::mathVariantValue( const QString& value ) const
{
if( value == "normal" )
return Normal;
else if( value == "bold" )
return Bold;
else if( value == "italic" )
return Italic;
else if( value == "bold-italic" )
return BoldItalic;
else if( value == "double-struck" )
return DoubleStruck;
else if( value == "bold-fraktur" )
return BoldFraktur;
else if( value == "script" )
return Script;
else if( value == "bold-script" )
return BoldScript;
else if( value == "fraktur" )
return Fraktur;
else if( value == "sans-serif" )
return SansSerif;
else if( value == "bold-sans-serif" )
return BoldSansSerif;
else if( value == "sans-serif-italic" )
return SansSerifItalic;
else if( value == "sans-serif-bold-italic" )
return SansSerifBoldItalic;
else if( value == "monospace" )
return Monospace;
else
return -1;
}
double AttributeManager::mathSpaceValue( const QString& value ) const
{
if( value == "negativeveryverythinmathspace" )
return -1*calculateEmExUnits( 0.055556, true );
else if( value == "negativeverythinmathspace" )
return -1*calculateEmExUnits( 0.111111, true );
else if( value == "negativethinmathspace" )
return -1*calculateEmExUnits( 0.166667, true );
else if( value == "negativemediummathspace" )
return -1*calculateEmExUnits( 0.222222, true );
else if( value == "negativethickmathspace" )
return -1*calculateEmExUnits( 0.277778, true );
else if( value == "negativeverythickmathspace" )
return -1*calculateEmExUnits( 0.333333, true );
else if( value == "negativeveryverythickmathspace" )
return -1*calculateEmExUnits( 0.388889, true );
else if( value == "veryverythinmathspace" )
return calculateEmExUnits( 0.055556, true );
else if( value == "verythinmathspace" )
return calculateEmExUnits( 0.111111, true );
else if( value == "thinmathspace" )
return calculateEmExUnits( 0.166667, true );
else if( value == "mediummathspace" )
return calculateEmExUnits( 0.222222, true );
else if( value == "thickmathspace" )
return calculateEmExUnits( 0.277778, true );
else if( value == "verythickmathspace" )
return calculateEmExUnits( 0.333333, true );
else if( value == "veryverythickmathspace" )
return calculateEmExUnits( 0.388889, true );
else
return -1.0;
}
QVariant AttributeManager::parseMetrics( const QString& value ) const
{
QString tmpValue = value.trimmed();
/* if( value.endsWith( "%" ) )
{
tmpValue.chop( 1 );
return defaultValueOf( m_attribute ) * (tmpValue.toDouble()/100);
}*/
QString unit = tmpValue.right( 2 );
tmpValue.chop( 2 );
if( unit == "em" )
return calculateEmExUnits( tmpValue.toDouble(), true );
else if( unit == "ex" )
return calculateEmExUnits( tmpValue.toDouble(), false );
else if( unit == "px" )
return m_viewConverter->viewToDocumentX( tmpValue.toInt() );
else if( unit == "in" || unit == "cm" || unit == "pc" || unit == "mm" ||
unit == "pt" )
return KoUnit::parseValue( value );
return QVariant();
}
double AttributeManager::calculateEmExUnits( double value, bool isEm ) const
{
// use a postscript paint device so that font metrics returns postscript points
KoPostscriptPaintDevice paintDevice;
QFontMetricsF fm( m_currentFont, &paintDevice );
if( isEm )
return value* fm.width( 'm' );
else
return value* fm.xHeight();
}
int AttributeManager::scriptLevel() const
{
return m_scriptLevelStack.top();
}
void AttributeManager::setViewConverter( KoViewConverter* converter )
{
m_viewConverter = converter;
}
} // namespace FormulaShape
/* This file is part of the KDE project
Copyright (C) 2006 Martin Pfeiffer <hubipete@gmx.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef ATTRIBUTEMANAGER_H
#define ATTRIBUTEMANAGER_H
#include <QStack>
#include <QFont>
#include <QVariant>
class KoViewConverter;
class QPaintDevice;
namespace FormulaShape {
class BasicElement;
enum MathVariant {
Normal,
Bold,
Italic,
BoldItalic,
DoubleStruck,
BoldFraktur,
Script,
BoldScript,
Fraktur,
SansSerif,
BoldSansSerif,
SansSerifItalic,
SansSerifBoldItalic,
Monospace
};
enum NamedSpaces {
NegativeVeryVeryThinMathSpace,
NegativeVeryThinMathSpace,
NegativeThinMathSpace,
NegativeMediumMathSpace,
NegativeThickMathSpace,
NegativeVeryThickMathSpace,
NegativeVeryVeryThickMathSpace,
VeryVeryThinMathSpace,
VeryThinMathSpace,
ThinMathSpace,
MediumMathSpace,
ThickMathSpace,
VeryThickMathSpace,
VeryVeryThickMathSpace
};
/** Enum encoding all possibilities to align */
enum Align {
Left /**< Align to the left*/,
Center /**< Align to the center*/,
Right /**< Align to the right*/
};
/** Enum encoding all states of mo's form attribute */
enum Form {
Prefix /**< mo is a prefix*/,
Infix /**< mo is a infix - used for all cases where it's not prefix or postfix*/,
Postfix /**< mo is a postfix*/
};
/** Enum encoding all states of mspace's linebreak attribute */
enum LineBreak {
Auto /**< Renderer should use default linebreaking algorithm*/,
NewLine /**< Start a new line and do not indent*/,
IndentingNewLine /**< Start a new line and do indent*/,
NoBreak /**< Do not allow a linebreak here*/,
GoodBreak /**< If a linebreak is needed on the line, here is a good spot*/,
BadBreak /**< If a linebreak is needed on the line, try to avoid breaking here*/
};
/**
* @short manages all the attributes, used by the elements to obtain attribute values
*
* The AttributeManager is the central point dealing with the MathML attributes and
* their values. It is in fact something like a StyleManager. As the normal elements
* only have a general hash list of the elements they hold, there is the need for a
* class that manages conversion and heritage of the attributes during the painting
* phase. These are the two main tasks of AttributeManager.
* The AttributeManager is always called when an element needs a value to work with.
* The AttributeManager looks for that value in its stack according to the heritage
* and if it does not find an appropriated value it returns a default.
* The AttributeManager stores its stacked BasicElements in a QList rather than a
* QStack because the former is faster doing a prepend().
* For conversion from QString to a QVariant mostly the build in QVariant methods
* are used. For the rest that can not be converted using QVariant the parseValue()
* method is used.
*
* @author Martin Pfeiffer <hubipete@gmx.net>
*/
class AttributeManager {
public:
/// The constructor
AttributeManager();
/// The destructor
~AttributeManager();
/**
* Obtain a value for attribute
* @param attribute A string with the attribute to look up
* @return QVariant with the value
*/
QVariant valueOf( const QString& attribute ) const;
Align alignValueOf( const QString& attribute ) const;
/**
* Inherit the attributes of an element
* @param element The BasicElement to herit from
*/
void inheritAttributes( const BasicElement* element );
/// Disenherit the attributes currently on top of the stack
void disinheritAttributes();
/// Obtain the @r current scriptlevel
int scriptLevel() const;
/// Obtain the @r current displystyle
bool displayStyle() const;
double mathSpaceValue( const QString& value ) const;
/// Set the KoViewConverter to use
void setViewConverter( KoViewConverter* converter );
protected:
/**
* Alter the current scriptlevel on the stack's top
* @param element The BasicElement that effects the changes to the scriptLevel
*/
void alterScriptLevel( const BasicElement* element );
QVariant parseValue( const QString& value ) const;
/**
* Fill the heritage stack with all the attributes valid for element
* @param element The BasicElement to build up the heritage stack for
*/
void buildHeritageOf( const BasicElement* element );
/**
* Calculates the pt values of a passes em or ex value
* @param value The em or ex value to be used for calculation
* @param isEm Indicates whether to calculate an ex or em value
* @return The calculated pt value
*/
double calculateEmExUnits( double value, bool isEm ) const;
QVariant parseMetrics( const QString& value ) const;
int formValue( const QString& value ) const;
int mathVariantValue( const QString& value ) const;
int alignValue( const QString& value ) const;
private:
/// The stack of attribute heritage, the topmost element is the currently active
QStack<const BasicElement*> m_attributeStack;
/// The stack for the current scriptlevel