|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
|
|
|
|
Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
|
|
|
|
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 <tqfontmetrics.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kprinter.h>
|
|
|
|
|
|
|
|
#include "contextstyle.h"
|
|
|
|
#include "elementvisitor.h"
|
|
|
|
#include "spaceelement.h"
|
|
|
|
|
|
|
|
|
|
|
|
KFORMULA_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
|
|
|
|
SpaceElement::SpaceElement( SpaceWidth space, bool tab, BasicElement* parent )
|
|
|
|
: BasicElement( parent ),
|
|
|
|
m_tab( tab ),
|
|
|
|
m_widthType( NoSize ),
|
|
|
|
m_heightType( NoSize ),
|
|
|
|
m_depthType( NoSize ),
|
|
|
|
m_lineBreak( NoBreakType )
|
|
|
|
{
|
|
|
|
// Backwards compatibility with KFO format
|
|
|
|
switch ( space ) {
|
|
|
|
case NEGTHIN:
|
|
|
|
m_widthType = NegativeThinMathSpace;
|
|
|
|
break;
|
|
|
|
case THIN:
|
|
|
|
m_widthType = ThinMathSpace;
|
|
|
|
break;
|
|
|
|
case MEDIUM:
|
|
|
|
m_widthType = MediumMathSpace;
|
|
|
|
break;
|
|
|
|
case THICK:
|
|
|
|
m_widthType = ThickMathSpace;
|
|
|
|
break;
|
|
|
|
case QUAD:
|
|
|
|
m_widthType = VeryVeryThickMathSpace;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SpaceElement::SpaceElement( const SpaceElement& other )
|
|
|
|
: BasicElement( other ),
|
|
|
|
m_widthType( other.m_widthType ),
|
|
|
|
m_width( other.m_width ),
|
|
|
|
m_heightType( other.m_heightType ),
|
|
|
|
m_height( other.m_height ),
|
|
|
|
m_depthType( other.m_depthType ),
|
|
|
|
m_depth( other.m_depth ),
|
|
|
|
m_lineBreak( other.m_lineBreak )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SpaceElement::accept( ElementVisitor* visitor )
|
|
|
|
{
|
|
|
|
return visitor->visit( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SpaceElement::calcSizes( const ContextStyle& context,
|
|
|
|
ContextStyle::TextStyle tstyle,
|
|
|
|
ContextStyle::IndexStyle /*istyle*/,
|
|
|
|
StyleAttributes& style )
|
|
|
|
{
|
|
|
|
double factor = style.sizeFactor();
|
|
|
|
luPt mySize = context.getAdjustedSize( tstyle, factor );
|
|
|
|
TQFont font = context.getDefaultFont();
|
|
|
|
font.setPointSize( mySize );
|
|
|
|
|
|
|
|
TQFontMetrics fm( font );
|
|
|
|
TQChar w = 'M';
|
|
|
|
LuPixelRect hbound = fm.boundingRect( w );
|
|
|
|
TQChar h = 'x';
|
|
|
|
LuPixelRect vbound = fm.boundingRect( h );
|
|
|
|
|
|
|
|
double width = style.getSpace( m_widthType, m_width );
|
|
|
|
if ( m_widthType == AbsoluteSize ) {
|
|
|
|
width = m_width / context.layoutUnitPtToPt( context.getBaseSize() );
|
|
|
|
}
|
|
|
|
else if ( m_widthType == PixelSize ) {
|
|
|
|
width = context.pixelYToPt( m_width ) / context.layoutUnitPtToPt( context.getBaseSize() );
|
|
|
|
}
|
|
|
|
double height = style.getSpace( m_heightType, m_height );
|
|
|
|
if ( m_heightType == AbsoluteSize ) {
|
|
|
|
height = m_height / context.layoutUnitPtToPt( context.getBaseSize() );
|
|
|
|
}
|
|
|
|
else if ( m_heightType == PixelSize ) {
|
|
|
|
height = context.pixelYToPt( m_height ) / context.layoutUnitPtToPt( context.getBaseSize() );
|
|
|
|
}
|
|
|
|
double depth = style.getSpace( m_depthType, m_depth );
|
|
|
|
if ( m_depthType == AbsoluteSize ) {
|
|
|
|
depth = m_depth / context.layoutUnitPtToPt( context.getBaseSize() );
|
|
|
|
}
|
|
|
|
else if ( m_depthType == PixelSize ) {
|
|
|
|
depth = context.pixelYToPt( m_depth ) / context.layoutUnitPtToPt( context.getBaseSize() );
|
|
|
|
}
|
|
|
|
|
|
|
|
setWidth( hbound.width() * width );
|
|
|
|
setHeight( vbound.height() * height + vbound.height() * depth );
|
|
|
|
setBaseline( vbound.height() * height );
|
|
|
|
|
|
|
|
if ( m_tab ) {
|
|
|
|
getParent()->registerTab( this );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpaceElement::draw( TQPainter& painter, const LuPixelRect& /*r*/,
|
|
|
|
const ContextStyle& context,
|
|
|
|
ContextStyle::TextStyle /*tstyle*/,
|
|
|
|
ContextStyle::IndexStyle /*istyle*/,
|
|
|
|
StyleAttributes& /*style*/,
|
|
|
|
const LuPixelPoint& parentOrigin )
|
|
|
|
{
|
|
|
|
LuPixelPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY());
|
|
|
|
// there is such a thing as negative space!
|
|
|
|
//if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
|
|
|
|
// return;
|
|
|
|
|
|
|
|
if ( context.edit() ) {
|
|
|
|
painter.setPen( context.getEmptyColor() );
|
|
|
|
painter.drawLine( context.layoutUnitToPixelX( myPos.x() ),
|
|
|
|
context.layoutUnitToPixelY( myPos.y()+getHeight() ),
|
|
|
|
context.layoutUnitToPixelX( myPos.x()+getWidth()-1 ),
|
|
|
|
context.layoutUnitToPixelY( myPos.y()+getHeight() ) );
|
|
|
|
painter.drawLine( context.layoutUnitToPixelX( myPos.x() ),
|
|
|
|
context.layoutUnitToPixelY( myPos.y()+getHeight() ),
|
|
|
|
context.layoutUnitToPixelX( myPos.x() ),
|
|
|
|
context.layoutUnitToPixelY( myPos.y()+getHeight()-getHeight()/5 ) );
|
|
|
|
painter.drawLine( context.layoutUnitToPixelX( myPos.x()+getWidth()-1 ),
|
|
|
|
context.layoutUnitToPixelY( myPos.y()+getHeight() ),
|
|
|
|
context.layoutUnitToPixelX( myPos.x()+getWidth()-1 ),
|
|
|
|
context.layoutUnitToPixelY( myPos.y()+getHeight()-getHeight()/5 ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SpaceElement::writeDom(TQDomElement element)
|
|
|
|
{
|
|
|
|
BasicElement::writeDom(element);
|
|
|
|
switch ( m_widthType ) {
|
|
|
|
case NegativeVeryVeryThinMathSpace:
|
|
|
|
case NegativeVeryThinMathSpace:
|
|
|
|
case NegativeThinMathSpace:
|
|
|
|
case NegativeMediumMathSpace:
|
|
|
|
case NegativeThickMathSpace:
|
|
|
|
case NegativeVeryThickMathSpace:
|
|
|
|
case NegativeVeryVeryThickMathSpace:
|
|
|
|
element.setAttribute( "WIDTH", "negthin" );
|
|
|
|
break;
|
|
|
|
case VeryVeryThinMathSpace:
|
|
|
|
case VeryThinMathSpace:
|
|
|
|
case ThinMathSpace:
|
|
|
|
element.setAttribute( "WIDTH", "thin" );
|
|
|
|
break;
|
|
|
|
case MediumMathSpace:
|
|
|
|
element.setAttribute( "WIDTH", "medium" );
|
|
|
|
break;
|
|
|
|
case ThickMathSpace:
|
|
|
|
element.setAttribute( "WIDTH", "thick" );
|
|
|
|
break;
|
|
|
|
case VeryThickMathSpace:
|
|
|
|
case VeryVeryThickMathSpace:
|
|
|
|
element.setAttribute( "WIDTH", "quad" );
|
|
|
|
break;
|
|
|
|
case AbsoluteSize:
|
|
|
|
case RelativeSize:
|
|
|
|
case PixelSize:
|
|
|
|
if ( m_width < 0 ) {
|
|
|
|
element.setAttribute( "WIDTH", "negthin" );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
element.setAttribute( "WIDTH", "thin" );
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ( m_tab ) {
|
|
|
|
element.setAttribute( "TAB", "true" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SpaceElement::readAttributesFromDom( TQDomElement element )
|
|
|
|
{
|
|
|
|
if ( !BasicElement::readAttributesFromDom( element ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
TQString widthStr = element.attribute( "WIDTH" );
|
|
|
|
if( !widthStr.isNull() ) {
|
|
|
|
if ( widthStr.lower() == "quad" ) {
|
|
|
|
m_widthType = VeryVeryThickMathSpace;
|
|
|
|
}
|
|
|
|
else if ( widthStr.lower() == "thick" ) {
|
|
|
|
m_widthType = ThickMathSpace;
|
|
|
|
}
|
|
|
|
else if ( widthStr.lower() == "medium" ) {
|
|
|
|
m_widthType = MediumMathSpace;
|
|
|
|
}
|
|
|
|
else if ( widthStr.lower() == "negthin" ) {
|
|
|
|
m_widthType = NegativeThinMathSpace;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_widthType = ThinMathSpace;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
TQString tabStr = element.attribute( "TAB" );
|
|
|
|
m_tab = !tabStr.isNull();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SpaceElement::readContentFromDom(TQDomNode& node)
|
|
|
|
{
|
|
|
|
return BasicElement::readContentFromDom( node );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SpaceElement::readAttributesFromMathMLDom(const TQDomElement& element)
|
|
|
|
{
|
|
|
|
if ( ! BasicElement::readAttributesFromMathMLDom( element ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString widthStr = element.attribute( "width" ).stripWhiteSpace().lower();
|
|
|
|
if ( ! widthStr.isNull() ) {
|
|
|
|
m_width = getSize( widthStr, &m_widthType );
|
|
|
|
if ( m_widthType == NoSize ) {
|
|
|
|
m_widthType = getSpace( widthStr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TQString heightStr = element.attribute( "height" ).stripWhiteSpace().lower();
|
|
|
|
if ( ! heightStr.isNull() ) {
|
|
|
|
m_height = getSize( heightStr, &m_heightType );
|
|
|
|
}
|
|
|
|
TQString depthStr = element.attribute( "depth" ).stripWhiteSpace().lower();
|
|
|
|
if ( ! depthStr.isNull() ) {
|
|
|
|
m_depth = getSize( depthStr, &m_depthType );
|
|
|
|
}
|
|
|
|
TQString linebreakStr = element.attribute( "linebreak" ).stripWhiteSpace().lower();
|
|
|
|
if ( ! linebreakStr.isNull() ) {
|
|
|
|
if ( linebreakStr == "auto" ) {
|
|
|
|
m_lineBreak = AutoBreak;
|
|
|
|
}
|
|
|
|
else if ( linebreakStr == "newline" ) {
|
|
|
|
m_lineBreak = NewLineBreak;
|
|
|
|
}
|
|
|
|
else if ( linebreakStr == "indentingnewline" ) {
|
|
|
|
m_lineBreak = IndentingNewLineBreak;
|
|
|
|
}
|
|
|
|
else if ( linebreakStr == "nobreak" ) {
|
|
|
|
m_lineBreak = NoBreak;
|
|
|
|
}
|
|
|
|
else if ( linebreakStr == "goodbreak" ) {
|
|
|
|
m_lineBreak = GoodBreak;
|
|
|
|
}
|
|
|
|
else if ( linebreakStr == "badbreak" ) {
|
|
|
|
m_lineBreak = BadBreak;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpaceElement::writeMathMLAttributes( TQDomElement& element ) const
|
|
|
|
{
|
|
|
|
switch ( m_widthType ) {
|
|
|
|
case AbsoluteSize:
|
|
|
|
element.setAttribute( "width", TQString( "%1pt" ).arg( m_width ) );
|
|
|
|
break;
|
|
|
|
case RelativeSize:
|
|
|
|
element.setAttribute( "width", TQString( "%1%" ).arg( m_width * 100.0 ) );
|
|
|
|
break;
|
|
|
|
case PixelSize:
|
|
|
|
element.setAttribute( "width", TQString( "%1px" ).arg( m_width ) );
|
|
|
|
break;
|
|
|
|
case NegativeVeryVeryThinMathSpace:
|
|
|
|
element.setAttribute( "width", "negativeveryverythinmathspace" );
|
|
|
|
break;
|
|
|
|
case NegativeVeryThinMathSpace:
|
|
|
|
element.setAttribute( "width", "negativeverythinmathspace" );
|
|
|
|
break;
|
|
|
|
case NegativeThinMathSpace:
|
|
|
|
element.setAttribute( "width", "negativethinmathspace" );
|
|
|
|
break;
|
|
|
|
case NegativeMediumMathSpace:
|
|
|
|
element.setAttribute( "width", "negativemediummathspace" );
|
|
|
|
break;
|
|
|
|
case NegativeThickMathSpace:
|
|
|
|
element.setAttribute( "width", "negativethickmathspace" );
|
|
|
|
break;
|
|
|
|
case NegativeVeryThickMathSpace:
|
|
|
|
element.setAttribute( "width", "negativeverythickmathspace" );
|
|
|
|
break;
|
|
|
|
case NegativeVeryVeryThickMathSpace:
|
|
|
|
element.setAttribute( "width", "negativeveryverythickmathspace" );
|
|
|
|
break;
|
|
|
|
case VeryVeryThinMathSpace:
|
|
|
|
element.setAttribute( "width", "veryverythinmathspace" );
|
|
|
|
break;
|
|
|
|
case VeryThinMathSpace:
|
|
|
|
element.setAttribute( "width", "verythinmathspace" );
|
|
|
|
break;
|
|
|
|
case ThinMathSpace:
|
|
|
|
element.setAttribute( "width", "thinmathspace" );
|
|
|
|
break;
|
|
|
|
case MediumMathSpace:
|
|
|
|
element.setAttribute( "width", "mediummathspace" );
|
|
|
|
break;
|
|
|
|
case ThickMathSpace:
|
|
|
|
element.setAttribute( "width", "thickmathspace" );
|
|
|
|
break;
|
|
|
|
case VeryThickMathSpace:
|
|
|
|
element.setAttribute( "width", "verythickmathspace" );
|
|
|
|
break;
|
|
|
|
case VeryVeryThickMathSpace:
|
|
|
|
element.setAttribute( "width", "veryverythickmathspace" );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch ( m_heightType ) {
|
|
|
|
case AbsoluteSize:
|
|
|
|
element.setAttribute( "height", TQString( "%1pt" ).arg( m_height ) );
|
|
|
|
break;
|
|
|
|
case RelativeSize:
|
|
|
|
element.setAttribute( "height", TQString( "%1%" ).arg( m_height * 100.0 ) );
|
|
|
|
break;
|
|
|
|
case PixelSize:
|
|
|
|
element.setAttribute( "height", TQString( "%1px" ).arg( m_height ) );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch ( m_depthType ) {
|
|
|
|
case AbsoluteSize:
|
|
|
|
element.setAttribute( "depth", TQString( "%1pt" ).arg( m_depth ) );
|
|
|
|
break;
|
|
|
|
case RelativeSize:
|
|
|
|
element.setAttribute( "depth", TQString( "%1%" ).arg( m_depth * 100.0 ) );
|
|
|
|
break;
|
|
|
|
case PixelSize:
|
|
|
|
element.setAttribute( "depth", TQString( "%1px" ).arg( m_depth ) );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch ( m_lineBreak ) {
|
|
|
|
case AutoBreak:
|
|
|
|
element.setAttribute( "linebreak", "auto" );
|
|
|
|
break;
|
|
|
|
case NewLineBreak:
|
|
|
|
element.setAttribute( "linebreak", "newline" );
|
|
|
|
break;
|
|
|
|
case IndentingNewLineBreak:
|
|
|
|
element.setAttribute( "linebreak", "indentingnewline" );
|
|
|
|
break;
|
|
|
|
case NoBreak:
|
|
|
|
element.setAttribute( "linebreak", "nobreak" );
|
|
|
|
break;
|
|
|
|
case GoodBreak:
|
|
|
|
element.setAttribute( "linebreak", "goodbreak" );
|
|
|
|
break;
|
|
|
|
case BadBreak:
|
|
|
|
element.setAttribute( "linebreak", "badbreak" );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString SpaceElement::toLatex()
|
|
|
|
{
|
|
|
|
switch ( m_widthType ) {
|
|
|
|
case NegativeVeryVeryThinMathSpace:
|
|
|
|
case NegativeVeryThinMathSpace:
|
|
|
|
case NegativeThinMathSpace:
|
|
|
|
case NegativeMediumMathSpace:
|
|
|
|
case NegativeThickMathSpace:
|
|
|
|
case NegativeVeryThickMathSpace:
|
|
|
|
case NegativeVeryVeryThickMathSpace:
|
|
|
|
return "\\!";
|
|
|
|
case VeryVeryThinMathSpace:
|
|
|
|
case VeryThinMathSpace:
|
|
|
|
case ThinMathSpace:
|
|
|
|
return "\\,";
|
|
|
|
case MediumMathSpace:
|
|
|
|
return "\\>";
|
|
|
|
case ThickMathSpace:
|
|
|
|
return "\\;";
|
|
|
|
case VeryThickMathSpace:
|
|
|
|
case VeryVeryThickMathSpace:
|
|
|
|
return "\\quad ";
|
|
|
|
case AbsoluteSize:
|
|
|
|
case RelativeSize:
|
|
|
|
case PixelSize:
|
|
|
|
if ( m_width < 0 ) {
|
|
|
|
return "\\!";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return "\\,";
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
KFORMULA_NAMESPACE_END
|