[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