qwt_text_engine.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
  2. * Qwt Widget Library
  3. * Copyright (C) 1997 Josef Wilgen
  4. * Copyright (C) 2003 Uwe Rathmann
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Qwt License, Version 1.0
  8. *****************************************************************************/
  9. #include "qwt_text_engine.h"
  10. #include "qwt_math.h"
  11. #include "qwt_painter.h"
  12. #include <qpainter.h>
  13. #include <qpixmap.h>
  14. #include <qimage.h>
  15. #include <qmap.h>
  16. #include <qwidget.h>
  17. #include <qtextobject.h>
  18. #include <qtextdocument.h>
  19. #include <qabstracttextdocumentlayout.h>
  20. static QString taggedRichText( const QString &text, int flags )
  21. {
  22. QString richText = text;
  23. // By default QSimpleRichText is Qt::AlignLeft
  24. if ( flags & Qt::AlignJustify )
  25. {
  26. richText.prepend( QString::fromLatin1( "<div align=\"justify\">" ) );
  27. richText.append( QString::fromLatin1( "</div>" ) );
  28. }
  29. else if ( flags & Qt::AlignRight )
  30. {
  31. richText.prepend( QString::fromLatin1( "<div align=\"right\">" ) );
  32. richText.append( QString::fromLatin1( "</div>" ) );
  33. }
  34. else if ( flags & Qt::AlignHCenter )
  35. {
  36. richText.prepend( QString::fromLatin1( "<div align=\"center\">" ) );
  37. richText.append( QString::fromLatin1( "</div>" ) );
  38. }
  39. return richText;
  40. }
  41. class QwtRichTextDocument: public QTextDocument
  42. {
  43. public:
  44. QwtRichTextDocument( const QString &text, int flags, const QFont &font )
  45. {
  46. setUndoRedoEnabled( false );
  47. setDefaultFont( font );
  48. setHtml( text );
  49. // make sure we have a document layout
  50. ( void )documentLayout();
  51. QTextOption option = defaultTextOption();
  52. if ( flags & Qt::TextWordWrap )
  53. option.setWrapMode( QTextOption::WordWrap );
  54. else
  55. option.setWrapMode( QTextOption::NoWrap );
  56. option.setAlignment( ( Qt::Alignment ) flags );
  57. setDefaultTextOption( option );
  58. QTextFrame *root = rootFrame();
  59. QTextFrameFormat fm = root->frameFormat();
  60. fm.setBorder( 0 );
  61. fm.setMargin( 0 );
  62. fm.setPadding( 0 );
  63. fm.setBottomMargin( 0 );
  64. fm.setLeftMargin( 0 );
  65. root->setFrameFormat( fm );
  66. adjustSize();
  67. }
  68. };
  69. class QwtPlainTextEngine::PrivateData
  70. {
  71. public:
  72. int effectiveAscent( const QFont &font ) const
  73. {
  74. const QString fontKey = font.key();
  75. QMap<QString, int>::const_iterator it =
  76. d_ascentCache.find( fontKey );
  77. if ( it == d_ascentCache.end() )
  78. {
  79. int ascent = findAscent( font );
  80. it = d_ascentCache.insert( fontKey, ascent );
  81. }
  82. return ( *it );
  83. }
  84. private:
  85. int findAscent( const QFont &font ) const
  86. {
  87. static const QString dummy( "E" );
  88. static const QColor white( Qt::white );
  89. const QFontMetrics fm( font );
  90. QPixmap pm( fm.width( dummy ), fm.height() );
  91. pm.fill( white );
  92. QPainter p( &pm );
  93. p.setFont( font );
  94. p.drawText( 0, 0, pm.width(), pm.height(), 0, dummy );
  95. p.end();
  96. const QImage img = pm.toImage();
  97. int row = 0;
  98. for ( row = 0; row < img.height(); row++ )
  99. {
  100. const QRgb *line = ( const QRgb * )img.scanLine( row );
  101. const int w = pm.width();
  102. for ( int col = 0; col < w; col++ )
  103. {
  104. if ( line[col] != white.rgb() )
  105. return fm.ascent() - row + 1;
  106. }
  107. }
  108. return fm.ascent();
  109. }
  110. mutable QMap<QString, int> d_ascentCache;
  111. };
  112. //! Constructor
  113. QwtTextEngine::QwtTextEngine()
  114. {
  115. }
  116. //! Destructor
  117. QwtTextEngine::~QwtTextEngine()
  118. {
  119. }
  120. //! Constructor
  121. QwtPlainTextEngine::QwtPlainTextEngine()
  122. {
  123. d_data = new PrivateData;
  124. }
  125. //! Destructor
  126. QwtPlainTextEngine::~QwtPlainTextEngine()
  127. {
  128. delete d_data;
  129. }
  130. /*!
  131. Find the height for a given width
  132. \param font Font of the text
  133. \param flags Bitwise OR of the flags used like in QPainter::drawText
  134. \param text Text to be rendered
  135. \param width Width
  136. \return Calculated height
  137. */
  138. double QwtPlainTextEngine::heightForWidth( const QFont& font, int flags,
  139. const QString& text, double width ) const
  140. {
  141. const QFontMetricsF fm( font );
  142. const QRectF rect = fm.boundingRect(
  143. QRectF( 0, 0, width, QWIDGETSIZE_MAX ), flags, text );
  144. return rect.height();
  145. }
  146. /*!
  147. Returns the size, that is needed to render text
  148. \param font Font of the text
  149. \param flags Bitwise OR of the flags used like in QPainter::drawText
  150. \param text Text to be rendered
  151. \return Caluclated size
  152. */
  153. QSizeF QwtPlainTextEngine::textSize( const QFont &font,
  154. int flags, const QString& text ) const
  155. {
  156. const QFontMetricsF fm( font );
  157. const QRectF rect = fm.boundingRect(
  158. QRectF( 0, 0, QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ), flags, text );
  159. return rect.size();
  160. }
  161. /*!
  162. Return margins around the texts
  163. \param font Font of the text
  164. \param left Return 0
  165. \param right Return 0
  166. \param top Return value for the top margin
  167. \param bottom Return value for the bottom margin
  168. */
  169. void QwtPlainTextEngine::textMargins( const QFont &font, const QString &,
  170. double &left, double &right, double &top, double &bottom ) const
  171. {
  172. left = right = top = 0;
  173. const QFontMetricsF fm( font );
  174. top = fm.ascent() - d_data->effectiveAscent( font );
  175. bottom = fm.descent();
  176. }
  177. /*!
  178. \brief Draw the text in a clipping rectangle
  179. A wrapper for QPainter::drawText.
  180. \param painter Painter
  181. \param rect Clipping rectangle
  182. \param flags Bitwise OR of the flags used like in QPainter::drawText
  183. \param text Text to be rendered
  184. */
  185. void QwtPlainTextEngine::draw( QPainter *painter, const QRectF &rect,
  186. int flags, const QString& text ) const
  187. {
  188. QwtPainter::drawText( painter, rect, flags, text );
  189. }
  190. /*!
  191. Test if a string can be rendered by this text engine.
  192. \return Always true. All texts can be rendered by QwtPlainTextEngine
  193. */
  194. bool QwtPlainTextEngine::mightRender( const QString & ) const
  195. {
  196. return true;
  197. }
  198. #ifndef QT_NO_RICHTEXT
  199. //! Constructor
  200. QwtRichTextEngine::QwtRichTextEngine()
  201. {
  202. }
  203. /*!
  204. Find the height for a given width
  205. \param font Font of the text
  206. \param flags Bitwise OR of the flags used like in QPainter::drawText
  207. \param text Text to be rendered
  208. \param width Width
  209. \return Calculated height
  210. */
  211. double QwtRichTextEngine::heightForWidth( const QFont& font, int flags,
  212. const QString& text, double width ) const
  213. {
  214. QwtRichTextDocument doc( text, flags, font );
  215. doc.setPageSize( QSizeF( width, QWIDGETSIZE_MAX ) );
  216. return doc.documentLayout()->documentSize().height();
  217. }
  218. /*!
  219. Returns the size, that is needed to render text
  220. \param font Font of the text
  221. \param flags Bitwise OR of the flags used like in QPainter::drawText
  222. \param text Text to be rendered
  223. \return Caluclated size
  224. */
  225. QSizeF QwtRichTextEngine::textSize( const QFont &font,
  226. int flags, const QString& text ) const
  227. {
  228. QwtRichTextDocument doc( text, flags, font );
  229. QTextOption option = doc.defaultTextOption();
  230. if ( option.wrapMode() != QTextOption::NoWrap )
  231. {
  232. option.setWrapMode( QTextOption::NoWrap );
  233. doc.setDefaultTextOption( option );
  234. doc.adjustSize();
  235. }
  236. return doc.size();
  237. }
  238. /*!
  239. Draw the text in a clipping rectangle
  240. \param painter Painter
  241. \param rect Clipping rectangle
  242. \param flags Bitwise OR of the flags like in for QPainter::drawText
  243. \param text Text to be rendered
  244. */
  245. void QwtRichTextEngine::draw( QPainter *painter, const QRectF &rect,
  246. int flags, const QString& text ) const
  247. {
  248. QwtRichTextDocument doc( text, flags, painter->font() );
  249. QwtPainter::drawSimpleRichText( painter, rect, flags, doc );
  250. }
  251. /*!
  252. Wrap text into <div align=...> </div> tags according flags
  253. \param text Text
  254. \param flags Bitwise OR of the flags like in for QPainter::drawText
  255. \return Tagged text
  256. */
  257. QString QwtRichTextEngine::taggedText( const QString &text, int flags ) const
  258. {
  259. return taggedRichText( text, flags );
  260. }
  261. /*!
  262. Test if a string can be rendered by this text engine
  263. \param text Text to be tested
  264. \return QStyleSheet::mightBeRichText(text);
  265. */
  266. bool QwtRichTextEngine::mightRender( const QString &text ) const
  267. {
  268. return Qt::mightBeRichText( text );
  269. }
  270. /*!
  271. Return margins around the texts
  272. \param left Return 0
  273. \param right Return 0
  274. \param top Return 0
  275. \param bottom Return 0
  276. */
  277. void QwtRichTextEngine::textMargins( const QFont &, const QString &,
  278. double &left, double &right, double &top, double &bottom ) const
  279. {
  280. left = right = top = bottom = 0;
  281. }
  282. #endif // !QT_NO_RICHTEXT