[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: koffice/kformula/flake
From: Alfredo Beaumont Sainz <alfredo.beaumont () gmail ! com>
Date: 2009-06-20 17:10:10
Message-ID: 1245517810.588661.31598.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 984392 by abeaumont:
Merge from kdelibs branch: Fix text layout issues once and for all
M +3 -3 AttributeManager.cpp
M +8 -2 GlyphElement.cpp
M +5 -2 GlyphElement.h
M +6 -2 IdentifierElement.cpp
M +1 -1 IdentifierElement.h
M +9 -2 NumberElement.cpp
M +1 -1 NumberElement.h
M +6 -3 OperatorElement.cpp
M +1 -1 OperatorElement.h
M +2 -1 StringElement.cpp
M +1 -1 StringElement.h
M +11 -2 TextElement.cpp
M +1 -1 TextElement.h
M +35 -13 TokenElement.cpp
M +3 -1 TokenElement.h
M +3 -3 UnderOverElement.cpp
--- trunk/koffice/kformula/flake/AttributeManager.cpp #984391:984392
@@ -209,11 +209,11 @@
return 0;
if(!unit.isEmpty()) {
if (unit.compare("em", Qt::CaseInsensitive) == 0) {
- QFontMetrics fm(font(element));
+ QFontMetricsF fm(font(element));
return fm.height() * number;
}
else if (unit.compare("ex", Qt::CaseInsensitive) == 0) {
- QFontMetrics fm(font(element));
+ QFontMetricsF fm(font(element));
return fm.xHeight() * number;
}
}
@@ -316,7 +316,7 @@
}
double AttributeManager::parseMathSpace( const QString& value, BasicElement *element \
) const {
- QFontMetrics fm(font(element));
+ QFontMetricsF fm(font(element));
qreal conversionEmToPixels = fm.xHeight();
if( value == "negativeveryverythinmathspace" )
--- trunk/koffice/kformula/flake/GlyphElement.cpp #984391:984392
@@ -24,13 +24,14 @@
#include <KoXmlReader.h>
#include <QFontDatabase>
+#include <QFontMetricsF>
#include <kdebug.h>
GlyphElement::GlyphElement( BasicElement* parent ) : TokenElement( parent )
{}
-void GlyphElement::renderToPath( const QString& raw, QPainterPath& path )
+QRectF GlyphElement::renderToPath( const QString& raw, QPainterPath& path )
{
// try to lookup the char in the font database
AttributeManager am;
@@ -44,9 +45,14 @@
tmpFont.setFamily( fontFamily );
path.addText( path.currentPosition(), tmpFont,
QChar( am.stringOf( "index", this ).toInt() ) );
+ QFontMetricsF fm(tmpFont);
+ return fm.boundingRect(QChar( am.stringOf( "index", this ).toInt() ) );
}
- else // if not found use alt text
+ else { // if not found use alt text
path.addText( path.currentPosition(), font(), am.stringOf( "alt", this ) );
+ QFontMetricsF fm(font());
+ return fm.boundingRect(am.stringOf( "alt", this ));
+ }
}
ElementType GlyphElement::elementType() const
--- trunk/koffice/kformula/flake/GlyphElement.h #984391:984392
@@ -27,7 +27,7 @@
/**
* @short Implementation of the MathML mglyph element
*
- * GlyphElement uses the the QT font database classes to load the additional fonts \
to + * GlyphElement uses the Qt font database classes to load the additional fonts to
* display its contents.
*/
class KOFORMULA_EXPORT GlyphElement : public TokenElement {
@@ -39,8 +39,11 @@
ElementType elementType() const;
/// Process @p raw and render it to @p path
- void renderToPath( const QString& raw, QPainterPath& path );
+ QRectF renderToPath( const QString& raw, QPainterPath& path );
+ /// get width of character, for layouting
+ double getWidth(const AttributeManager *am);
+
private:
bool readMathMLAttributes( const KoXmlElement& element );
void writeMathMLAttributes( KoXmlWriter* writer ) const;
--- trunk/koffice/kformula/flake/IdentifierElement.cpp #984391:984392
@@ -20,17 +20,21 @@
#include "IdentifierElement.h"
#include "AttributeManager.h"
#include "Dictionary.h"
+#include <QFontMetricsF>
#include <kdebug.h>
IdentifierElement::IdentifierElement( BasicElement* parent ) : TokenElement( parent \
) {}
-void IdentifierElement::renderToPath( const QString& raw, QPainterPath& path )
+QRectF IdentifierElement::renderToPath( const QString& raw, QPainterPath& path )
{
AttributeManager manager;
- path.addText( path.currentPosition(), manager.font( this ), "hallo" );
+ QFont font = manager.font(this);
+ path.addText( path.currentPosition(), font, raw );
+ QFontMetricsF fm(font);
+ return fm.boundingRect(raw);
}
ElementType IdentifierElement::elementType() const
--- trunk/koffice/kformula/flake/IdentifierElement.h #984391:984392
@@ -38,7 +38,7 @@
ElementType elementType() const;
/// Process @p raw and render it to @p path
- void renderToPath( const QString& raw, QPainterPath& path );
+ QRectF renderToPath( const QString& raw, QPainterPath& path );
};
#endif // IDENTIFIERELEMENT_H
--- trunk/koffice/kformula/flake/NumberElement.cpp #984391:984392
@@ -18,14 +18,21 @@
Boston, MA 02110-1301, USA.
*/
+#include <QFontMetricsF>
+
#include "NumberElement.h"
+#include "AttributeManager.h"
NumberElement::NumberElement( BasicElement* parent ) : TokenElement( parent )
{}
-void NumberElement::renderToPath( const QString& rawString, QPainterPath& path )
+QRectF NumberElement::renderToPath( const QString& rawString, QPainterPath& path )
{
- path.addText( path.currentPosition(), font(), rawString );
+ AttributeManager manager;
+ QFont font = manager.font(this);
+ path.addText( path.currentPosition(), font, rawString );
+ QFontMetricsF fm(font);
+ return fm.boundingRect(rawString);
}
ElementType NumberElement::elementType() const
--- trunk/koffice/kformula/flake/NumberElement.h #984391:984392
@@ -39,7 +39,7 @@
ElementType elementType() const;
/// Process @p raw and render it to @p path
- void renderToPath( const QString& raw, QPainterPath& path );
+ QRectF renderToPath( const QString& raw, QPainterPath& path );
};
#endif // NUMBERELEMENT_H
--- trunk/koffice/kformula/flake/OperatorElement.cpp #984391:984392
@@ -17,6 +17,7 @@
Boston, MA 02110-1301, USA.
*/
+#include <QFontMetricsF>
#include "OperatorElement.h"
#include "RowElement.h"
#include "AttributeManager.h"
@@ -30,7 +31,7 @@
return QPainterPath();
}
-void OperatorElement::renderToPath( const QString& raw, QPainterPath& path )
+QRectF OperatorElement::renderToPath( const QString& raw, QPainterPath& path )
{
Dictionary dict;
dict.queryOperator( raw, determineOperatorForm() );
@@ -39,8 +40,10 @@
qreal rSpace = manager.parseMathSpace(dict.rSpace(), this);
qreal lSpace = manager.parseMathSpace(dict.lSpace(), this);
path.moveTo( path.currentPosition() + QPointF( lSpace, 0.0 ) );
- path.addText( path.currentPosition(), manager.font( this ), raw );
- path.moveTo( path.boundingRect().right() + rSpace, 0 );
+ QFont font = manager.font(this);
+ path.addText( path.currentPosition(), font, raw );
+ QFontMetricsF fm(font);
+ return fm.boundingRect(QRect(), Qt::TextIncludeTrailingSpaces, \
raw).adjusted(0,0,lSpace+rSpace,0).adjusted(0,-fm.ascent(), 0, -fm.ascent()); }
Form OperatorElement::determineOperatorForm() const
--- trunk/koffice/kformula/flake/OperatorElement.h #984391:984392
@@ -48,7 +48,7 @@
ElementType elementType() const;
/// Process @p raw and render it to @p path
- void renderToPath( const QString& raw, QPainterPath& path );
+ QRectF renderToPath( const QString& raw, QPainterPath& path );
private:
/// @return The Form value that was passed as QString @p value
--- trunk/koffice/kformula/flake/StringElement.cpp #984391:984392
@@ -22,8 +22,9 @@
StringElement::StringElement( BasicElement* parent ) : TokenElement( parent )
{}
-void StringElement::renderToPath( const QString& raw, QPainterPath& path )
+QRectF StringElement::renderToPath( const QString& raw, QPainterPath& path )
{
+ return QRectF();
}
ElementType StringElement::elementType() const
--- trunk/koffice/kformula/flake/StringElement.h #984391:984392
@@ -34,7 +34,7 @@
/// @return The element's ElementType
ElementType elementType() const;
- void renderToPath( const QString& raw, QPainterPath& path );
+ QRectF renderToPath( const QString& raw, QPainterPath& path );
};
#endif // STRINGELEMENT_H
--- trunk/koffice/kformula/flake/TextElement.cpp #984391:984392
@@ -20,14 +20,23 @@
*/
#include "TextElement.h"
+#include "AttributeManager.h"
+#include <QFontMetricsF>
#include <KoXmlWriter.h>
+#include <kdebug.h>
TextElement::TextElement( BasicElement* parent ) : TokenElement( parent )
{}
-void TextElement::renderToPath( const QString& raw, QPainterPath& path )
+QRectF TextElement::renderToPath( const QString& raw, QPainterPath& path )
{
- path.addText( path.currentPosition(), font(), raw );
+ AttributeManager manager;
+
+ QFont font = manager.font(this);
+ path.addText( path.currentPosition(), font, raw );
+ QFontMetricsF fm(font);
+ QRectF box = fm.boundingRect(QRect(), Qt::TextIncludeTrailingSpaces, \
raw).adjusted(0,-fm.ascent(),0,-fm.ascent()); + return box;
}
ElementType TextElement::elementType() const
--- trunk/koffice/kformula/flake/TextElement.h #984391:984392
@@ -38,7 +38,7 @@
/// @return The element's ElementType
ElementType elementType() const;
- void renderToPath( const QString& raw, QPainterPath& path );
+ QRectF renderToPath( const QString& raw, QPainterPath& path );
};
#endif // TEXTELEMENT_H
--- trunk/koffice/kformula/flake/TokenElement.cpp #984391:984392
@@ -50,7 +50,7 @@
// set the painter to foreground color and paint the text in the content path
painter.setPen( am->colorOf( "mathcolor", this ) );
painter.setBrush( QBrush( painter.pen().color() ) );
- painter.translate( 0, baseLine() );
+ painter.translate( m_xoffset, baseLine() );
painter.drawPath( m_contentPath );
}
@@ -58,34 +58,56 @@
{
// Query the font to use
m_font = am->font( this );
+ QFontMetricsF fm(m_font);
// save the token in an empty path
m_contentPath = QPainterPath();
- // replace all the object replacement characters with glyphs
- if(m_glyphs.isEmpty())//optimize for the common case
- renderToPath(m_rawString, m_contentPath);
- else {
+ /* Current bounding box. Note that the left can be negative, for italics etc */
+ QRectF boundingrect;
+ if(m_glyphs.isEmpty()) {//optimize for the common case
+ boundingrect = renderToPath(m_rawString, m_contentPath);
+ } else {
+ // replace all the object replacement characters with glyphs
+ // We have to keep track of the bounding box at all times
QString chunk;
int counter = 0;
for( int i = 0; i < m_rawString.length(); i++ ) {
if( m_rawString[ i ] != QChar::ObjectReplacementCharacter )
chunk.append( m_rawString[ i ] );
else {
- renderToPath( chunk, m_contentPath );
- m_glyphs[ counter ]->renderToPath( QString(), m_contentPath );
+ m_contentPath.moveTo(boundingrect.right(), 0);
+ QRectF newbox = renderToPath( chunk, m_contentPath );
+ boundingrect.setRight( boundingrect.right() + newbox.right());
+ boundingrect.setTop( qMax(boundingrect.top(), newbox.top()));
+ boundingrect.setBottom( qMax(boundingrect.bottom(), \
newbox.bottom())); +
+ m_contentPath.moveTo(boundingrect.right(), 0);
+ newbox = m_glyphs[ counter ]->renderToPath( QString(), m_contentPath \
); + boundingrect.setRight( boundingrect.right() + newbox.right());
+ boundingrect.setTop( qMax(boundingrect.top(), newbox.top()));
+ boundingrect.setBottom( qMax(boundingrect.bottom(), \
newbox.bottom())); +
counter++;
chunk.clear();
}
+ if( !chunk.isEmpty() ) {
+ m_contentPath.moveTo(boundingrect.right(), 0);
+ QRectF newbox = renderToPath( chunk, m_contentPath );
+ boundingrect.setRight( boundingrect.right() + newbox.right());
+ boundingrect.setTop( qMax(boundingrect.top(), newbox.top()));
+ boundingrect.setBottom( qMax(boundingrect.bottom(), \
newbox.bottom())); + }
}
- if( !chunk.isEmpty() )
- renderToPath( chunk, m_contentPath );
}
- // As the text is added to ( 0 / 0 ) the baseline equals the top edge of the
+ //The left side may be negative, because of italised letters etc. we need to \
adjust for this when painting + //The qMax is just incase. The bounding box left \
should never be >0 + m_xoffset = qMax(-boundingrect.left(), (qreal)0.0);
+ // As the text is added to (0,0) the baseline equals the top edge of the
// elements bounding rect, while translating it down the text's baseline moves \
too
- setBaseLine( -m_contentPath.boundingRect().y() ); // set baseline accordingly
- setWidth( m_contentPath.boundingRect().right() );
- setHeight( m_contentPath.boundingRect().height() );
+ setBaseLine( -boundingrect.y() ); // set baseline accordingly
+ setWidth( boundingrect.right() + m_xoffset );
+ setHeight( boundingrect.height() );
}
void TokenElement::insertChild( FormulaCursor* cursor, BasicElement* child )
--- trunk/koffice/kformula/flake/TokenElement.h #984391:984392
@@ -95,7 +95,7 @@
double cursorOffset( const FormulaCursor* cursor ) const;
/// Process @p raw and render it to @p path
- virtual void renderToPath( const QString& raw, QPainterPath& path ) = 0;
+ virtual QRectF renderToPath( const QString& raw, QPainterPath& path ) = 0;
protected:
/// Read contents of the token element. Content should be unicode text strings \
or mglyphs @@ -119,6 +119,8 @@
/// A painter path holding text content for fast painting
QPainterPath m_contentPath;
+ /// x offset for painting the path
+ qreal m_xoffset;
};
#endif // TOKENELEMENT_H
--- trunk/koffice/kformula/flake/UnderOverElement.cpp #984391:984392
@@ -85,10 +85,10 @@
if(m_elementType != Over) {
origin.setX( ( largestWidth - m_underElement->width())/2.0 );
/* Try to be smart about where to place the under */
-/* if(m_baseElement->baseLine() + 1.5*thinSpace > m_baseElement->height())
+// if(m_baseElement->baseLine() + 1.5*thinSpace > m_baseElement->height())
origin.setY( origin.y() + m_baseElement->baseLine() + (accentUnder ? \
thinSpace/2 : thinSpace ));
- else */
- origin.setY( origin.y() + m_baseElement->height() + (accentUnder ? \
thinSpace/2 : thinSpace) ); +// else
+// origin.setY( origin.y() + m_baseElement->height() + (accentUnder ? \
thinSpace/2 : thinSpace) ); m_underElement->setOrigin( origin );
setHeight( origin.y() + m_underElement->height() );
} else {
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic