00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_text_engine.h"
00011 #include "qwt_math.h"
00012 #include "qwt_painter.h"
00013 #include <qpainter.h>
00014 #include <qpixmap.h>
00015 #include <qimage.h>
00016 #include <qmap.h>
00017 #include <qwidget.h>
00018 #include <qtextobject.h>
00019 #include <qtextdocument.h>
00020 #include <qabstracttextdocumentlayout.h>
00021
00022 static QString taggedRichText( const QString &text, int flags )
00023 {
00024 QString richText = text;
00025
00026
00027 if ( flags & Qt::AlignJustify )
00028 {
00029 richText.prepend( QString::fromLatin1( "<div align=\"justify\">" ) );
00030 richText.append( QString::fromLatin1( "</div>" ) );
00031 }
00032 else if ( flags & Qt::AlignRight )
00033 {
00034 richText.prepend( QString::fromLatin1( "<div align=\"right\">" ) );
00035 richText.append( QString::fromLatin1( "</div>" ) );
00036 }
00037 else if ( flags & Qt::AlignHCenter )
00038 {
00039 richText.prepend( QString::fromLatin1( "<div align=\"center\">" ) );
00040 richText.append( QString::fromLatin1( "</div>" ) );
00041 }
00042
00043 return richText;
00044 }
00045
00046 class QwtRichTextDocument: public QTextDocument
00047 {
00048 public:
00049 QwtRichTextDocument( const QString &text, int flags, const QFont &font )
00050 {
00051 setUndoRedoEnabled( false );
00052 setDefaultFont( font );
00053 setHtml( text );
00054
00055
00056 ( void )documentLayout();
00057
00058 QTextOption option = defaultTextOption();
00059 if ( flags & Qt::TextWordWrap )
00060 option.setWrapMode( QTextOption::WordWrap );
00061 else
00062 option.setWrapMode( QTextOption::NoWrap );
00063
00064 option.setAlignment( static_cast<Qt::Alignment>( flags ) );
00065 setDefaultTextOption( option );
00066
00067 QTextFrame *root = rootFrame();
00068 QTextFrameFormat fm = root->frameFormat();
00069 fm.setBorder( 0 );
00070 fm.setMargin( 0 );
00071 fm.setPadding( 0 );
00072 fm.setBottomMargin( 0 );
00073 fm.setLeftMargin( 0 );
00074 root->setFrameFormat( fm );
00075
00076 adjustSize();
00077 }
00078 };
00079
00080 class QwtPlainTextEngine::PrivateData
00081 {
00082 public:
00083 int effectiveAscent( const QFont &font ) const
00084 {
00085 const QString fontKey = font.key();
00086
00087 QMap<QString, int>::const_iterator it =
00088 d_ascentCache.find( fontKey );
00089 if ( it == d_ascentCache.end() )
00090 {
00091 int ascent = findAscent( font );
00092 it = d_ascentCache.insert( fontKey, ascent );
00093 }
00094
00095 return ( *it );
00096 }
00097
00098 private:
00099 static int findAscent( const QFont &font )
00100 {
00101 static const QString dummy( "E" );
00102 static const QColor white( Qt::white );
00103
00104 const QFontMetrics fm( font );
00105 QPixmap pm( fm.width( dummy ), fm.height() );
00106 pm.fill( white );
00107
00108 QPainter p( &pm );
00109 p.setFont( font );
00110 p.drawText( 0, 0, pm.width(), pm.height(), 0, dummy );
00111 p.end();
00112
00113 const QImage img = pm.toImage();
00114
00115 int row = 0;
00116 for ( row = 0; row < img.height(); row++ )
00117 {
00118 const QRgb *line = reinterpret_cast<const QRgb *>(
00119 img.scanLine( row ) );
00120
00121 const int w = pm.width();
00122 for ( int col = 0; col < w; col++ )
00123 {
00124 if ( line[col] != white.rgb() )
00125 return fm.ascent() - row + 1;
00126 }
00127 }
00128
00129 return fm.ascent();
00130 }
00131
00132 mutable QMap<QString, int> d_ascentCache;
00133 };
00134
00136 QwtTextEngine::QwtTextEngine()
00137 {
00138 }
00139
00141 QwtTextEngine::~QwtTextEngine()
00142 {
00143 }
00144
00146 QwtPlainTextEngine::QwtPlainTextEngine()
00147 {
00148 d_data = new PrivateData;
00149 }
00150
00152 QwtPlainTextEngine::~QwtPlainTextEngine()
00153 {
00154 delete d_data;
00155 }
00156
00167 double QwtPlainTextEngine::heightForWidth( const QFont& font, int flags,
00168 const QString& text, double width ) const
00169 {
00170 const QFontMetricsF fm( font );
00171 const QRectF rect = fm.boundingRect(
00172 QRectF( 0, 0, width, QWIDGETSIZE_MAX ), flags, text );
00173
00174 return rect.height();
00175 }
00176
00186 QSizeF QwtPlainTextEngine::textSize( const QFont &font,
00187 int flags, const QString& text ) const
00188 {
00189 const QFontMetricsF fm( font );
00190 const QRectF rect = fm.boundingRect(
00191 QRectF( 0, 0, QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ), flags, text );
00192
00193 return rect.size();
00194 }
00195
00205 void QwtPlainTextEngine::textMargins( const QFont &font, const QString &,
00206 double &left, double &right, double &top, double &bottom ) const
00207 {
00208 left = right = top = 0;
00209
00210 const QFontMetricsF fm( font );
00211 top = fm.ascent() - d_data->effectiveAscent( font );
00212 bottom = fm.descent();
00213 }
00214
00225 void QwtPlainTextEngine::draw( QPainter *painter, const QRectF &rect,
00226 int flags, const QString& text ) const
00227 {
00228 QwtPainter::drawText( painter, rect, flags, text );
00229 }
00230
00235 bool QwtPlainTextEngine::mightRender( const QString & ) const
00236 {
00237 return true;
00238 }
00239
00240 #ifndef QT_NO_RICHTEXT
00241
00243 QwtRichTextEngine::QwtRichTextEngine()
00244 {
00245 }
00246
00257 double QwtRichTextEngine::heightForWidth( const QFont& font, int flags,
00258 const QString& text, double width ) const
00259 {
00260 QwtRichTextDocument doc( text, flags, font );
00261
00262 doc.setPageSize( QSizeF( width, QWIDGETSIZE_MAX ) );
00263 return doc.documentLayout()->documentSize().height();
00264 }
00265
00276 QSizeF QwtRichTextEngine::textSize( const QFont &font,
00277 int flags, const QString& text ) const
00278 {
00279 QwtRichTextDocument doc( text, flags, font );
00280
00281 QTextOption option = doc.defaultTextOption();
00282 if ( option.wrapMode() != QTextOption::NoWrap )
00283 {
00284 option.setWrapMode( QTextOption::NoWrap );
00285 doc.setDefaultTextOption( option );
00286 doc.adjustSize();
00287 }
00288
00289 return doc.size();
00290 }
00291
00300 void QwtRichTextEngine::draw( QPainter *painter, const QRectF &rect,
00301 int flags, const QString& text ) const
00302 {
00303 QwtRichTextDocument doc( text, flags, painter->font() );
00304 QwtPainter::drawSimpleRichText( painter, rect, flags, doc );
00305 }
00306
00315 QString QwtRichTextEngine::taggedText( const QString &text, int flags ) const
00316 {
00317 return taggedRichText( text, flags );
00318 }
00319
00326 bool QwtRichTextEngine::mightRender( const QString &text ) const
00327 {
00328 return Qt::mightBeRichText( text );
00329 }
00330
00339 void QwtRichTextEngine::textMargins( const QFont &, const QString &,
00340 double &left, double &right, double &top, double &bottom ) const
00341 {
00342 left = right = top = bottom = 0;
00343 }
00344
00345 #endif // !QT_NO_RICHTEXT