123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
- * Qwt Widget Library
- * Copyright (C) 1997 Josef Wilgen
- * Copyright (C) 2003 Uwe Rathmann
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the Qwt License, Version 1.0
- *****************************************************************************/
- #include "qwt_text_engine.h"
- #include "qwt_math.h"
- #include "qwt_painter.h"
- #include <qpainter.h>
- #include <qpixmap.h>
- #include <qimage.h>
- #include <qmap.h>
- #include <qwidget.h>
- #include <qtextobject.h>
- #include <qtextdocument.h>
- #include <qabstracttextdocumentlayout.h>
- static QString taggedRichText( const QString &text, int flags )
- {
- QString richText = text;
- // By default QSimpleRichText is Qt::AlignLeft
- if ( flags & Qt::AlignJustify )
- {
- richText.prepend( QString::fromLatin1( "<div align=\"justify\">" ) );
- richText.append( QString::fromLatin1( "</div>" ) );
- }
- else if ( flags & Qt::AlignRight )
- {
- richText.prepend( QString::fromLatin1( "<div align=\"right\">" ) );
- richText.append( QString::fromLatin1( "</div>" ) );
- }
- else if ( flags & Qt::AlignHCenter )
- {
- richText.prepend( QString::fromLatin1( "<div align=\"center\">" ) );
- richText.append( QString::fromLatin1( "</div>" ) );
- }
- return richText;
- }
- class QwtRichTextDocument: public QTextDocument
- {
- public:
- QwtRichTextDocument( const QString &text, int flags, const QFont &font )
- {
- setUndoRedoEnabled( false );
- setDefaultFont( font );
- setHtml( text );
- // make sure we have a document layout
- ( void )documentLayout();
- QTextOption option = defaultTextOption();
- if ( flags & Qt::TextWordWrap )
- option.setWrapMode( QTextOption::WordWrap );
- else
- option.setWrapMode( QTextOption::NoWrap );
- option.setAlignment( ( Qt::Alignment ) flags );
- setDefaultTextOption( option );
- QTextFrame *root = rootFrame();
- QTextFrameFormat fm = root->frameFormat();
- fm.setBorder( 0 );
- fm.setMargin( 0 );
- fm.setPadding( 0 );
- fm.setBottomMargin( 0 );
- fm.setLeftMargin( 0 );
- root->setFrameFormat( fm );
- adjustSize();
- }
- };
- class QwtPlainTextEngine::PrivateData
- {
- public:
- int effectiveAscent( const QFont &font ) const
- {
- const QString fontKey = font.key();
- QMap<QString, int>::const_iterator it =
- d_ascentCache.find( fontKey );
- if ( it == d_ascentCache.end() )
- {
- int ascent = findAscent( font );
- it = d_ascentCache.insert( fontKey, ascent );
- }
- return ( *it );
- }
- private:
- int findAscent( const QFont &font ) const
- {
- static const QString dummy( "E" );
- static const QColor white( Qt::white );
- const QFontMetrics fm( font );
- QPixmap pm( fm.width( dummy ), fm.height() );
- pm.fill( white );
- QPainter p( &pm );
- p.setFont( font );
- p.drawText( 0, 0, pm.width(), pm.height(), 0, dummy );
- p.end();
- const QImage img = pm.toImage();
- int row = 0;
- for ( row = 0; row < img.height(); row++ )
- {
- const QRgb *line = ( const QRgb * )img.scanLine( row );
- const int w = pm.width();
- for ( int col = 0; col < w; col++ )
- {
- if ( line[col] != white.rgb() )
- return fm.ascent() - row + 1;
- }
- }
- return fm.ascent();
- }
- mutable QMap<QString, int> d_ascentCache;
- };
- //! Constructor
- QwtTextEngine::QwtTextEngine()
- {
- }
- //! Destructor
- QwtTextEngine::~QwtTextEngine()
- {
- }
- //! Constructor
- QwtPlainTextEngine::QwtPlainTextEngine()
- {
- d_data = new PrivateData;
- }
- //! Destructor
- QwtPlainTextEngine::~QwtPlainTextEngine()
- {
- delete d_data;
- }
- /*!
- Find the height for a given width
- \param font Font of the text
- \param flags Bitwise OR of the flags used like in QPainter::drawText
- \param text Text to be rendered
- \param width Width
- \return Calculated height
- */
- double QwtPlainTextEngine::heightForWidth( const QFont& font, int flags,
- const QString& text, double width ) const
- {
- const QFontMetricsF fm( font );
- const QRectF rect = fm.boundingRect(
- QRectF( 0, 0, width, QWIDGETSIZE_MAX ), flags, text );
- return rect.height();
- }
- /*!
- Returns the size, that is needed to render text
- \param font Font of the text
- \param flags Bitwise OR of the flags used like in QPainter::drawText
- \param text Text to be rendered
- \return Caluclated size
- */
- QSizeF QwtPlainTextEngine::textSize( const QFont &font,
- int flags, const QString& text ) const
- {
- const QFontMetricsF fm( font );
- const QRectF rect = fm.boundingRect(
- QRectF( 0, 0, QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ), flags, text );
- return rect.size();
- }
- /*!
- Return margins around the texts
- \param font Font of the text
- \param left Return 0
- \param right Return 0
- \param top Return value for the top margin
- \param bottom Return value for the bottom margin
- */
- void QwtPlainTextEngine::textMargins( const QFont &font, const QString &,
- double &left, double &right, double &top, double &bottom ) const
- {
- left = right = top = 0;
- const QFontMetricsF fm( font );
- top = fm.ascent() - d_data->effectiveAscent( font );
- bottom = fm.descent();
- }
- /*!
- \brief Draw the text in a clipping rectangle
- A wrapper for QPainter::drawText.
- \param painter Painter
- \param rect Clipping rectangle
- \param flags Bitwise OR of the flags used like in QPainter::drawText
- \param text Text to be rendered
- */
- void QwtPlainTextEngine::draw( QPainter *painter, const QRectF &rect,
- int flags, const QString& text ) const
- {
- QwtPainter::drawText( painter, rect, flags, text );
- }
- /*!
- Test if a string can be rendered by this text engine.
- \return Always true. All texts can be rendered by QwtPlainTextEngine
- */
- bool QwtPlainTextEngine::mightRender( const QString & ) const
- {
- return true;
- }
- #ifndef QT_NO_RICHTEXT
- //! Constructor
- QwtRichTextEngine::QwtRichTextEngine()
- {
- }
- /*!
- Find the height for a given width
- \param font Font of the text
- \param flags Bitwise OR of the flags used like in QPainter::drawText
- \param text Text to be rendered
- \param width Width
- \return Calculated height
- */
- double QwtRichTextEngine::heightForWidth( const QFont& font, int flags,
- const QString& text, double width ) const
- {
- QwtRichTextDocument doc( text, flags, font );
- doc.setPageSize( QSizeF( width, QWIDGETSIZE_MAX ) );
- return doc.documentLayout()->documentSize().height();
- }
- /*!
- Returns the size, that is needed to render text
- \param font Font of the text
- \param flags Bitwise OR of the flags used like in QPainter::drawText
- \param text Text to be rendered
- \return Caluclated size
- */
- QSizeF QwtRichTextEngine::textSize( const QFont &font,
- int flags, const QString& text ) const
- {
- QwtRichTextDocument doc( text, flags, font );
- QTextOption option = doc.defaultTextOption();
- if ( option.wrapMode() != QTextOption::NoWrap )
- {
- option.setWrapMode( QTextOption::NoWrap );
- doc.setDefaultTextOption( option );
- doc.adjustSize();
- }
- return doc.size();
- }
- /*!
- Draw the text in a clipping rectangle
- \param painter Painter
- \param rect Clipping rectangle
- \param flags Bitwise OR of the flags like in for QPainter::drawText
- \param text Text to be rendered
- */
- void QwtRichTextEngine::draw( QPainter *painter, const QRectF &rect,
- int flags, const QString& text ) const
- {
- QwtRichTextDocument doc( text, flags, painter->font() );
- QwtPainter::drawSimpleRichText( painter, rect, flags, doc );
- }
- /*!
- Wrap text into <div align=...> </div> tags according flags
- \param text Text
- \param flags Bitwise OR of the flags like in for QPainter::drawText
- \return Tagged text
- */
- QString QwtRichTextEngine::taggedText( const QString &text, int flags ) const
- {
- return taggedRichText( text, flags );
- }
- /*!
- Test if a string can be rendered by this text engine
- \param text Text to be tested
- \return QStyleSheet::mightBeRichText(text);
- */
- bool QwtRichTextEngine::mightRender( const QString &text ) const
- {
- return Qt::mightBeRichText( text );
- }
- /*!
- Return margins around the texts
- \param left Return 0
- \param right Return 0
- \param top Return 0
- \param bottom Return 0
- */
- void QwtRichTextEngine::textMargins( const QFont &, const QString &,
- double &left, double &right, double &top, double &bottom ) const
- {
- left = right = top = bottom = 0;
- }
- #endif // !QT_NO_RICHTEXT
|