Newer
Older
/* -*- 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 );
QTextOption option = defaultTextOption();
if ( flags & Qt::TextWordWrap )
option.setAlignment( static_cast<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:
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 );
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 = reinterpret_cast<const QRgb *>(
img.scanLine( row ) );
if ( line[col] != white.rgb() )
return fm.ascent() - row + 1;
}
}
return fm.ascent();
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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
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
const QFontMetricsF fm( font );
top = fm.ascent() - d_data->effectiveAscent( font );
bottom = fm.descent();
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
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 flags Bitwise OR of the flags used like in QPainter::drawText()
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 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
if ( option.wrapMode() != QTextOption::NoWrap )
{
option.setWrapMode( QTextOption::NoWrap );
doc.setDefaultTextOption( option );
}
/*!
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()
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()
QString QwtRichTextEngine::taggedText( const QString &text, int flags ) const
}
/*!
Test if a string can be rendered by this text engine
\param text Text to be tested
bool QwtRichTextEngine::mightRender( const QString &text ) const
}
/*!
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