Qt 4.8
qstatictext.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qstatictext.h"
43 #include "qstatictext_p.h"
44 #include <private/qtextengine_p.h>
45 #include <private/qfontengine_p.h>
47 
48 #include <QtGui/qapplication.h>
49 
51 
161  : data(new QStaticTextPrivate)
162 {
163 }
164 
169  : data(new QStaticTextPrivate)
170 {
171  data->text = text;
172  data->invalidate();
173 }
174 
179 {
180  data = other.data;
181 }
182 
187 {
188  Q_ASSERT(!data || data->ref >= 1);
189 }
190 
195 {
196  if (data->ref != 1)
197  data.detach();
198 }
199 
216 void QStaticText::prepare(const QTransform &matrix, const QFont &font)
217 {
218  data->matrix = matrix;
219  data->font = font;
220  data->init();
221 }
222 
223 
228 {
229  data = other.data;
230  return *this;
231 }
232 
237 bool QStaticText::operator==(const QStaticText &other) const
238 {
239  return (data == other.data
240  || (data->text == other.data->text
241  && data->font == other.data->font
242  && data->textWidth == other.data->textWidth));
243 }
244 
249 bool QStaticText::operator!=(const QStaticText &other) const
250 {
251  return !(*this == other);
252 }
253 
262 {
263  detach();
264  data->text = text;
265  data->invalidate();
266 }
267 
280 {
281  detach();
283  data->invalidate();
284 }
285 
292 {
293  return Qt::TextFormat(data->textFormat);
294 }
295 
302 {
303  return data->text;
304 }
305 
319 {
320  if ((performanceHint == ModerateCaching && !data->useBackendOptimizations)
321  || (performanceHint == AggressiveCaching && data->useBackendOptimizations)) {
322  return;
323  }
324  detach();
325  data->useBackendOptimizations = (performanceHint == AggressiveCaching);
326  data->invalidate();
327 }
328 
335 {
337 }
338 
345 {
346  detach();
348  data->invalidate();
349 }
350 
355 {
356  return data->textOption;
357 }
358 
373 {
374  detach();
376  data->invalidate();
377 }
378 
385 {
386  return data->textWidth;
387 }
388 
395 {
396  if (data->needsRelayout)
397  data->init();
398  return data->actualSize;
399 }
400 
402  : textWidth(-1.0), items(0), itemCount(0), glyphPool(0), positionPool(0), charPool(0),
403  needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText),
404  untransformedCoordinates(false)
405 {
406 }
407 
409  : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix),
413 {
414 }
415 
417 {
418  delete[] items;
419  delete[] glyphPool;
420  delete[] positionPool;
421  delete[] charPool;
422 }
423 
425 {
426  return q->data.data();
427 }
428 
429 namespace {
430 
431  class DrawTextItemRecorder: public QPaintEngine
432  {
433  public:
434  DrawTextItemRecorder(bool untransformedCoordinates, bool useBackendOptimizations)
435  : m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations),
436  m_untransformedCoordinates(untransformedCoordinates), m_currentColor(Qt::black)
437  {
438  }
439 
440  virtual void updateState(const QPaintEngineState &newState)
441  {
442  if (newState.state() & QPaintEngine::DirtyPen
443  && newState.pen().color() != m_currentColor) {
444  m_dirtyPen = true;
445  m_currentColor = newState.pen().color();
446  }
447  }
448 
449  virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
450  {
451  const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
452 
453  QStaticTextItem currentItem;
454  currentItem.setFontEngine(ti.fontEngine);
455  currentItem.font = ti.font();
456  currentItem.charOffset = m_chars.size();
457  currentItem.numChars = ti.num_chars;
458  currentItem.glyphOffset = m_glyphs.size(); // Store offset into glyph pool
459  currentItem.positionOffset = m_glyphs.size(); // Offset into position pool
460  currentItem.useBackendOptimizations = m_useBackendOptimizations;
461  if (m_dirtyPen)
462  currentItem.color = m_currentColor;
463 
464  QTransform matrix = m_untransformedCoordinates ? QTransform() : state->transform();
465  matrix.translate(position.x(), position.y());
466 
469  ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
470 
471  int size = glyphs.size();
472  Q_ASSERT(size == positions.size());
473  currentItem.numGlyphs = size;
474 
475  m_glyphs.resize(m_glyphs.size() + size);
476  m_positions.resize(m_glyphs.size());
477  m_chars.resize(m_chars.size() + ti.num_chars);
478 
479  glyph_t *glyphsDestination = m_glyphs.data() + currentItem.glyphOffset;
480  memcpy(glyphsDestination, glyphs.constData(), sizeof(glyph_t) * currentItem.numGlyphs);
481 
482  QFixedPoint *positionsDestination = m_positions.data() + currentItem.positionOffset;
483  memcpy(positionsDestination, positions.constData(), sizeof(QFixedPoint) * currentItem.numGlyphs);
484 
485  QChar *charsDestination = m_chars.data() + currentItem.charOffset;
486  memcpy(charsDestination, ti.chars, sizeof(QChar) * currentItem.numChars);
487 
488  m_items.append(currentItem);
489  }
490 
491  virtual void drawPolygon(const QPointF *, int , PolygonDrawMode )
492  {
493  /* intentionally empty */
494  }
495 
496  virtual bool begin(QPaintDevice *) { return true; }
497  virtual bool end() { return true; }
498  virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
499  virtual Type type() const
500  {
501  return User;
502  }
503 
505  {
506  return m_items;
507  }
508 
510  {
511  return m_positions;
512  }
513 
514  QVector<glyph_t> glyphs() const
515  {
516  return m_glyphs;
517  }
518 
519  QVector<QChar> chars() const
520  {
521  return m_chars;
522  }
523 
524  private:
525  QVector<QStaticTextItem> m_items;
526  QVector<QFixedPoint> m_positions;
527  QVector<glyph_t> m_glyphs;
528  QVector<QChar> m_chars;
529 
530  bool m_dirtyPen;
531  bool m_useBackendOptimizations;
532  bool m_untransformedCoordinates;
533  QColor m_currentColor;
534  };
535 
536  class DrawTextItemDevice: public QPaintDevice
537  {
538  public:
539  DrawTextItemDevice(bool untransformedCoordinates, bool useBackendOptimizations)
540  {
541  m_paintEngine = new DrawTextItemRecorder(untransformedCoordinates,
542  useBackendOptimizations);
543  }
544 
545  ~DrawTextItemDevice()
546  {
547  delete m_paintEngine;
548  }
549 
550  int metric(PaintDeviceMetric m) const
551  {
552  int val;
553  switch (m) {
554  case PdmWidth:
555  case PdmHeight:
556  case PdmWidthMM:
557  case PdmHeightMM:
558  val = 0;
559  break;
560  case PdmDpiX:
561  case PdmPhysicalDpiX:
562  val = qt_defaultDpiX();
563  break;
564  case PdmDpiY:
565  case PdmPhysicalDpiY:
566  val = qt_defaultDpiY();
567  break;
568  case PdmNumColors:
569  val = 16777216;
570  break;
571  case PdmDepth:
572  val = 24;
573  break;
574  default:
575  val = 0;
576  qWarning("DrawTextItemDevice::metric: Invalid metric command");
577  }
578  return val;
579  }
580 
581  virtual QPaintEngine *paintEngine() const
582  {
583  return m_paintEngine;
584  }
585 
586  QVector<glyph_t> glyphs() const
587  {
588  return m_paintEngine->glyphs();
589  }
590 
592  {
593  return m_paintEngine->positions();
594  }
595 
597  {
598  return m_paintEngine->items();
599  }
600 
601  QVector<QChar> chars() const
602  {
603  return m_paintEngine->chars();
604  }
605 
606  private:
607  DrawTextItemRecorder *m_paintEngine;
608  };
609 }
610 
611 void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p)
612 {
613  bool preferRichText = textFormat == Qt::RichText
615 
616  if (!preferRichText) {
617  QTextLayout textLayout;
618  textLayout.setText(text);
619  textLayout.setFont(font);
620  textLayout.setTextOption(textOption);
621 
622  qreal leading = QFontMetricsF(font).leading();
623  qreal height = -leading;
624 
625  textLayout.beginLayout();
626  while (1) {
627  QTextLine line = textLayout.createLine();
628  if (!line.isValid())
629  break;
630 
631  if (textWidth >= 0.0)
632  line.setLineWidth(textWidth);
633  height += leading;
634  line.setPosition(QPointF(0.0, height));
635  height += line.height();
636  }
637  textLayout.endLayout();
638 
639  actualSize = textLayout.boundingRect().size();
640  textLayout.draw(p, topLeftPosition);
641  } else {
642  QTextDocument document;
643 #ifndef QT_NO_CSSPARSER
644  QColor color = p->pen().color();
645  document.setDefaultStyleSheet(QString::fromLatin1("body { color: #%1%2%3 }")
646  .arg(QString::number(color.red(), 16), 2, QLatin1Char('0'))
647  .arg(QString::number(color.green(), 16), 2, QLatin1Char('0'))
648  .arg(QString::number(color.blue(), 16), 2, QLatin1Char('0')));
649 #endif
650  document.setDefaultFont(font);
651  document.setDocumentMargin(0.0);
652 #ifndef QT_NO_TEXTHTMLPARSER
653  document.setHtml(text);
654 #else
655  document.setPlainText(text);
656 #endif
657  if (textWidth >= 0.0)
658  document.setTextWidth(textWidth);
659  else
660  document.adjustSize();
662 
663  p->save();
664  p->translate(topLeftPosition);
666  ctx.palette.setColor(QPalette::Text, p->pen().color());
667  document.documentLayout()->draw(p, ctx);
668  p->restore();
669 
670  if (textWidth >= 0.0)
671  document.adjustSize(); // Find optimal size
672 
673  actualSize = document.size();
674  }
675 }
676 
678 {
679  delete[] items;
680  delete[] glyphPool;
681  delete[] positionPool;
682  delete[] charPool;
683 
684  position = QPointF(0, 0);
685 
686  DrawTextItemDevice device(untransformedCoordinates, useBackendOptimizations);
687  {
688  QPainter painter(&device);
689  painter.setFont(font);
690  painter.setTransform(matrix);
691 
692  paintText(QPointF(0, 0), &painter);
693  }
694 
695  QVector<QStaticTextItem> deviceItems = device.items();
696  QVector<QFixedPoint> positions = device.positions();
697  QVector<glyph_t> glyphs = device.glyphs();
698  QVector<QChar> chars = device.chars();
699 
700  itemCount = deviceItems.size();
702 
703  glyphPool = new glyph_t[glyphs.size()];
704  memcpy(glyphPool, glyphs.constData(), glyphs.size() * sizeof(glyph_t));
705 
706  positionPool = new QFixedPoint[positions.size()];
707  memcpy(positionPool, positions.constData(), positions.size() * sizeof(QFixedPoint));
708 
709  charPool = new QChar[chars.size()];
710  memcpy(charPool, chars.constData(), chars.size() * sizeof(QChar));
711 
712  for (int i=0; i<itemCount; ++i) {
713  items[i] = deviceItems.at(i);
714 
717  items[i].chars = charPool + items[i].charOffset;
718  }
719 
720  needsRelayout = false;
721 }
722 
724 {
725  if (m_userData != 0 && !m_userData->ref.deref())
726  delete m_userData;
727  if (!m_fontEngine->ref.deref())
728  delete m_fontEngine;
729 }
730 
732 {
733  if (m_fontEngine != 0) {
734  if (!m_fontEngine->ref.deref())
735  delete m_fontEngine;
736  }
737 
738  m_fontEngine = fe;
739  if (m_fontEngine != 0)
740  m_fontEngine->ref.ref();
741 }
742 
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
QAtomicInt ref
void setTransform(const QTransform &transform, bool combine=false)
Sets the world transformation matrix.
Definition: qpainter.cpp:9547
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
void setTextFormat(Qt::TextFormat textFormat)
Sets the text format of the QStaticText to textFormat.
QFontEngine * fontEngine
const T * constData() const
void setText(const QString &string)
Sets the layout&#39;s text to the given string.
QPaintEngine::DirtyFlags state() const
Returns a combination of flags identifying the set of properties that need to be updated when updatin...
Definition: qpaintengine.h:292
QStaticText()
Constructs an empty QStaticText.
int type
Definition: qmetatype.cpp:239
~QStaticText()
Destroys the QStaticText.
double qreal
Definition: qglobal.h:1193
The QStaticText class enables optimized drawing of text when the text and its layout is updated rarel...
Definition: qstatictext.h:60
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void setPosition(const QPointF &pos)
Moves the line to position pos.
void prepare(const QTransform &matrix=QTransform(), const QFont &font=QFont())
Prepares the QStaticText object for being painted with the given matrix and the given font to avoid o...
QFixedPoint * positionPool
const QChar * chars
QFixedPoint * glyphPositions
Q_GUI_EXPORT int qt_defaultDpiY()
Definition: qfont.cpp:201
void adjustSize()
Adjusts the document to a reasonable size.
RenderFlags flags
unsigned char untransformedCoordinates
Q_GUI_EXPORT int qt_defaultDpiX()
Definition: qfont.cpp:162
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
void setFont(const QFont &f)
Sets the layout&#39;s font to the given font.
The QTextLine class represents a line of text inside a QTextLayout.
Definition: qtextlayout.h:197
void restore()
Restores the current painter state (pops a saved state off the stack).
Definition: qpainter.cpp:1620
Q_GUI_EXPORT bool mightBeRichText(const QString &)
Returns true if the string text is likely to be rich text; otherwise returns false.
QStaticTextItem * items
void setPerformanceHint(PerformanceHint performanceHint)
Sets the performance hint of the QStaticText according to the performanceHint provided.
QColor color() const
Returns the color of this pen&#39;s brush.
Definition: qpen.cpp:771
QRectF boundingRect() const
The smallest rectangle that contains all the lines in the layout.
void setLineWidth(qreal width)
Lays out the line with the given width.
bool ref()
Atomically increments the value of this QAtomicInt.
QTransform & translate(qreal dx, qreal dy)
Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to t...
Definition: qtransform.cpp:417
ushort red
Returns the red color component of this color.
Definition: qcolor.h:243
The QString class provides a Unicode character string.
Definition: qstring.h:83
QPalette palette
the default color that is used for the text, when no color is specified.
void setText(const QString &text)
Sets the text of the QStaticText to text.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool isValid() const
Returns true if this text line is valid; otherwise returns false.
Definition: qtextlayout.h:201
The QSizeF class defines the size of a two-dimensional object using floating point precision...
Definition: qsize.h:202
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QTextOption textOption
void setFontEngine(QFontEngine *fe)
void save()
Saves the current painter state (pushes the state onto a stack).
Definition: qpainter.cpp:1590
void setDefaultTextOption(const QTextOption &option)
Sets the default text option.
void setTextWidth(qreal textWidth)
Sets the preferred width for this QStaticText.
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
QExplicitlySharedDataPointer< QStaticTextPrivate > data
Definition: qstatictext.h:99
QStaticText & operator=(const QStaticText &)
Assigns other to this QStaticText.
static QStaticTextPrivate * get(const QStaticText *q)
QGlyphLayout glyphs
void setPlainText(const QString &text)
Replaces the entire contents of the document with the given plain text.
T * data() const
Returns a pointer to the shared data object.
Definition: qshareddata.h:145
const QPen & pen() const
Returns the painter&#39;s current pen.
Definition: qpainter.cpp:4152
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
char useBackendOptimizations
bool operator!=(const QStaticText &) const
Compares other to this QStaticText.
PerformanceHint performanceHint() const
Returns which performance hint is set for the QStaticText.
static const QCssKnownValue positions[NumKnownPositionModes - 1]
Definition: qcssparser.cpp:329
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray< glyph_t > &glyphs_out, QVarLengthArray< QFixedPoint > &positions)
Q_CORE_EXPORT void qWarning(const char *,...)
Internal QTextItem.
PerformanceHint
This enum the different performance hints that can be set on the QStaticText.
Definition: qstatictext.h:63
static const char * data(const QByteArray &arr)
QSizeF size
Returns the actual size of the document.
void setHtml(const QString &html)
Replaces the entire contents of the document with the given HTML-formatted text in the html string...
Qt::TextFormat textFormat() const
Returns the text format of the QStaticText.
void draw(QPainter *p, const QPointF &pos, const QVector< FormatRange > &selections=QVector< FormatRange >(), const QRectF &clip=QRectF()) const
Draws the whole layout on the painter p at the position specified by pos.
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
bool operator==(const QStaticText &) const
Compares other to this QStaticText.
TextFormat
Definition: qnamespace.h:1310
QTextOption textOption() const
Returns the current text option used to control the layout process.
void setDefaultFont(const QFont &font)
Sets the default font to use in the document layout.
The QTextLayout class is used to lay out and render text.
Definition: qtextlayout.h:105
QSizeF size() const
Returns the size of the bounding rect for this QStaticText.
void setTextOption(const QTextOption &textOption)
Sets the text option structure that controls the layout process to the given textOption.
ushort blue
Returns the blue color component of this color.
Definition: qcolor.h:245
qreal leading() const
Returns the leading of the font.
void setTextWidth(qreal width)
unsigned char textFormat
The QFont class specifies a font used for drawing text.
Definition: qfont.h:64
QTextLine createLine()
Returns a new text line to be laid out if there is text to be inserted into the layout; otherwise ret...
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
qreal textWidth() const
Returns the preferred width for this QStaticText.
void setTextOption(const QTextOption &option)
Sets the text option structure that controls the layout process to the given option.
#define ctx
Definition: qgl.cpp:6094
QAbstractTextDocumentLayout * documentLayout() const
Returns the document layout for this document.
void setColor(ColorGroup cg, ColorRole cr, const QColor &color)
Sets the color in the specified color group, used for the given color role, to the specified solid co...
Definition: qpalette.h:201
The QAbstractTextDocumentLayout::PaintContext class is a convenience class defining the parameters us...
void detach()
If the shared data object&#39;s reference count is greater than 1, this function creates a deep copy of t...
Definition: qshareddata.h:148
Definition: qnamespace.h:54
The QTextOption class provides a description of general rich text properties.
Definition: qtextoption.h:59
void setDocumentMargin(qreal margin)
unsigned char useBackendOptimizations
QSizeF size() const
Returns the size of the rectangle.
Definition: qrect.h:713
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
The QTextDocument class holds formatted text that can be viewed and edited using a QTextEdit...
void setDefaultStyleSheet(const QString &sheet)
The QPaintEngineState class provides information about the active paint engine&#39;s current state...
Definition: qpaintengine.h:289
The QFontMetricsF class provides font metrics information.
Definition: qfontmetrics.h:145
void setFont(const QFont &f)
Sets the painter&#39;s font to the given font.
Definition: qpainter.cpp:4288
unsigned char needsRelayout
const T * constData() const
Returns a const pointer to the data stored in the vector.
Definition: qvector.h:154
QPen pen() const
Returns the pen in the current paint engine state.
Definition: qpainter.cpp:9259
void endLayout()
Ends the layout process.
QString text() const
Returns the text of the QStaticText.
The QTextItem class provides all the information required to draw text in a custom paint engine...
Definition: qpaintengine.h:68
static const KeyPair *const end
ushort green
Returns the green color component of this color.
Definition: qcolor.h:244
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
QFont font() const
Returns the font that should be used to draw the text.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
qreal height() const
Returns the line&#39;s height.
unsigned int glyph_t
void beginLayout()
Begins the layout process.
void paintText(const QPointF &pos, QPainter *p)
int size() const
virtual void draw(QPainter *painter, const PaintContext &context)=0
Draws the layout with the given painter using the given context.
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
glyph_t * glyphs
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
Definition: qpainter.cpp:3311