|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the test suite of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
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> |
|
46 |
|
47 #include <QtGui/qapplication.h> |
|
48 |
|
49 QT_BEGIN_NAMESPACE |
|
50 |
|
51 /*! |
|
52 \class QStaticText |
|
53 \brief The QStaticText class enables optimized drawing of text when the text and its layout |
|
54 is updated rarely. |
|
55 \since 4.7 |
|
56 |
|
57 \ingroup multimedia |
|
58 \ingroup text |
|
59 \mainclass |
|
60 |
|
61 QStaticText provides a way to cache layout data for a block of text so that it can be drawn |
|
62 more efficiently than by using QPainter::drawText() in which the layout information is |
|
63 recalculated with every call. |
|
64 |
|
65 The class primarily provides an optimization for cases where the text, its font and the |
|
66 transformations on the painter are static over several paint events. If the text or its layout |
|
67 is changed for every iteration, QPainter::drawText() is the more efficient alternative, since |
|
68 the static text's layout would have to be recalculated to take the new state into consideration. |
|
69 |
|
70 Translating the painter will not cause the layout of the text to be recalculated, but will cause |
|
71 a very small performance impact on drawStaticText(). Altering any other parts of the painter's |
|
72 transformation or the painter's font will cause the layout of the static text to be |
|
73 recalculated. This should be avoided as often as possible to maximize the performance |
|
74 benefit of using QStaticText. |
|
75 |
|
76 In addition, only affine transformations are supported by drawStaticText(). Calling |
|
77 drawStaticText() on a projected painter will perform slightly worse than using the regular |
|
78 drawText() call, so this should be avoided. |
|
79 |
|
80 \code |
|
81 class MyWidget: public QWidget |
|
82 { |
|
83 public: |
|
84 MyWidget(QWidget *parent = 0) : QWidget(parent), m_staticText("This is static text") |
|
85 |
|
86 protected: |
|
87 void paintEvent(QPaintEvent *) |
|
88 { |
|
89 QPainter painter(this); |
|
90 painter.drawStaticText(0, 0, m_staticText); |
|
91 } |
|
92 |
|
93 private: |
|
94 QStaticText m_staticText; |
|
95 }; |
|
96 \endcode |
|
97 |
|
98 The QStaticText class can be used to mimic the behavior of QPainter::drawText() to a specific |
|
99 point with no boundaries, and also when QPainter::drawText() is called with a bounding |
|
100 rectangle. |
|
101 |
|
102 If a bounding rectangle is not required, create a QStaticText object without setting a preferred |
|
103 text width. The text will then occupy a single line. |
|
104 |
|
105 If you set a text width on the QStaticText object, this will bound the text. The text will |
|
106 be formatted so that no line exceeds the given width. The text width set for QStaticText will |
|
107 not automatically be used for clipping. To achieve clipping in addition to line breaks, use |
|
108 QPainter::setClipRect(). The position of the text is decided by the argument passed to |
|
109 QPainter::drawStaticText() and can change from call to call with a minimal impact on |
|
110 performance. |
|
111 |
|
112 QStaticText will attempt to guess the format of the input text using Qt::mightBeRichText(). |
|
113 To force QStaticText to display its contents as either plain text or rich text, use the |
|
114 function QStaticText::setTextFormat() and pass in, respectively, Qt::PlainText and |
|
115 Qt::RichText. |
|
116 |
|
117 If it's the first time the static text is drawn, or if the static text, or the painter's font |
|
118 or matrix have been altered since the last time it was drawn, the text's layout has to be |
|
119 recalculated. This will impose an overhead on the QPainter::drawStaticText() call where the |
|
120 relayout occurs. To avoid this overhead in the paint event, you can call prepare() ahead of |
|
121 time to ensure that the layout is calculated. |
|
122 |
|
123 \sa QPainter::drawText(), QPainter::drawStaticText(), QTextLayout, QTextDocument |
|
124 */ |
|
125 |
|
126 /*! |
|
127 \enum QStaticText::PerformanceHint |
|
128 |
|
129 This enum the different performance hints that can be set on the QStaticText. These hints |
|
130 can be used to indicate that the QStaticText should use additional caches, if possible, |
|
131 to improve performance at the expense of memory. In particular, setting the performance hint |
|
132 AggressiveCaching on the QStaticText will improve performance when using the OpenGL graphics |
|
133 system or when drawing to a QGLWidget. |
|
134 |
|
135 \value ModerateCaching Do basic caching for high performance at a low memory cost. |
|
136 \value AggressiveCaching Use additional caching when available. This may improve performance |
|
137 at a higher memory cost. |
|
138 */ |
|
139 |
|
140 /*! |
|
141 Constructs an empty QStaticText |
|
142 */ |
|
143 QStaticText::QStaticText() |
|
144 : data(new QStaticTextPrivate) |
|
145 { |
|
146 } |
|
147 |
|
148 /*! |
|
149 Constructs a QStaticText object with the given \a text and bounded by the given \a size. |
|
150 |
|
151 If an invalid size is passed for \a size the text will be unbounded. |
|
152 */ |
|
153 QStaticText::QStaticText(const QString &text) |
|
154 : data(new QStaticTextPrivate) |
|
155 { |
|
156 data->text = text; |
|
157 data->invalidate(); |
|
158 } |
|
159 |
|
160 /*! |
|
161 Constructs a QStaticText object which is a copy of \a other. |
|
162 */ |
|
163 QStaticText::QStaticText(const QStaticText &other) |
|
164 { |
|
165 data = other.data; |
|
166 } |
|
167 |
|
168 /*! |
|
169 Destroys the QStaticText. |
|
170 */ |
|
171 QStaticText::~QStaticText() |
|
172 { |
|
173 Q_ASSERT(!data || data->ref >= 1); |
|
174 } |
|
175 |
|
176 /*! |
|
177 \internal |
|
178 */ |
|
179 void QStaticText::detach() |
|
180 { |
|
181 if (data->ref != 1) |
|
182 data.detach(); |
|
183 } |
|
184 |
|
185 /*! |
|
186 Prepares the QStaticText object for being painted with the given \a matrix and the given \a font |
|
187 to avoid overhead when the actual drawStaticText() call is made. |
|
188 |
|
189 When drawStaticText() is called, the layout of the QStaticText will be recalculated if any part |
|
190 of the QStaticText object has changed since the last time it was drawn. It will also be |
|
191 recalculated if the painter's font or matrix are not the same as when the QStaticText was last |
|
192 drawn. |
|
193 |
|
194 To avoid the overhead of creating the layout the first time you draw the QStaticText after |
|
195 making changes, you can use the prepare() function and pass in the \a matrix and \a font you |
|
196 expect to use when drawing the text. |
|
197 |
|
198 \sa QPainter::setFont(), QPainter::setMatrix() |
|
199 */ |
|
200 void QStaticText::prepare(const QTransform &matrix, const QFont &font) |
|
201 { |
|
202 data->matrix = matrix; |
|
203 data->font = font; |
|
204 data->init(); |
|
205 } |
|
206 |
|
207 |
|
208 /*! |
|
209 Assigns \a other to this QStaticText. |
|
210 */ |
|
211 QStaticText &QStaticText::operator=(const QStaticText &other) |
|
212 { |
|
213 data = other.data; |
|
214 return *this; |
|
215 } |
|
216 |
|
217 /*! |
|
218 Compares \a other to this QStaticText. Returns true if the texts, fonts and text widths |
|
219 are equal. |
|
220 */ |
|
221 bool QStaticText::operator==(const QStaticText &other) const |
|
222 { |
|
223 return (data == other.data |
|
224 || (data->text == other.data->text |
|
225 && data->font == other.data->font |
|
226 && data->textWidth == other.data->textWidth)); |
|
227 } |
|
228 |
|
229 /*! |
|
230 Compares \a other to this QStaticText. Returns true if the texts, fonts or maximum sizes |
|
231 are different. |
|
232 */ |
|
233 bool QStaticText::operator!=(const QStaticText &other) const |
|
234 { |
|
235 return !(*this == other); |
|
236 } |
|
237 |
|
238 /*! |
|
239 Sets the text of the QStaticText to \a text. |
|
240 |
|
241 \note This function will cause the layout of the text to require recalculation. |
|
242 |
|
243 \sa text() |
|
244 */ |
|
245 void QStaticText::setText(const QString &text) |
|
246 { |
|
247 detach(); |
|
248 data->text = text; |
|
249 data->invalidate(); |
|
250 } |
|
251 |
|
252 /*! |
|
253 Sets the text format of the QStaticText to \a textFormat. If \a textFormat is set to |
|
254 Qt::AutoText (the default), the format of the text will try to be determined using the |
|
255 function Qt::mightBeRichText(). If the text format is Qt::PlainText, then the text will be |
|
256 displayed as is, whereas it will be interpreted as HTML if the format is Qt::RichText. HTML tags |
|
257 that alter the font of the text, its color, or its layout are supported by QStaticText. |
|
258 |
|
259 \note This function will cause the layout of the text to require recalculation. |
|
260 |
|
261 \sa textFormat(), setText(), text() |
|
262 */ |
|
263 void QStaticText::setTextFormat(Qt::TextFormat textFormat) |
|
264 { |
|
265 detach(); |
|
266 data->textFormat = textFormat; |
|
267 data->invalidate(); |
|
268 } |
|
269 |
|
270 /*! |
|
271 Returns the text format of the QStaticText. |
|
272 |
|
273 \sa setTextFormat(), setText(), text() |
|
274 */ |
|
275 Qt::TextFormat QStaticText::textFormat() const |
|
276 { |
|
277 return Qt::TextFormat(data->textFormat); |
|
278 } |
|
279 |
|
280 /*! |
|
281 Returns the text of the QStaticText. |
|
282 |
|
283 \sa setText() |
|
284 */ |
|
285 QString QStaticText::text() const |
|
286 { |
|
287 return data->text; |
|
288 } |
|
289 |
|
290 /*! |
|
291 Sets the performance hint of the QStaticText according to the \a |
|
292 performanceHint provided. The \a performanceHint is used to |
|
293 customize how much caching is done internally to improve |
|
294 performance. |
|
295 |
|
296 The default is QStaticText::ModerateCaching. |
|
297 |
|
298 \note This function will cause the layout of the text to require recalculation. |
|
299 |
|
300 \sa performanceHint() |
|
301 */ |
|
302 void QStaticText::setPerformanceHint(PerformanceHint performanceHint) |
|
303 { |
|
304 if ((performanceHint == ModerateCaching && !data->useBackendOptimizations) |
|
305 || (performanceHint == AggressiveCaching && data->useBackendOptimizations)) { |
|
306 return; |
|
307 } |
|
308 detach(); |
|
309 data->useBackendOptimizations = (performanceHint == AggressiveCaching); |
|
310 data->invalidate(); |
|
311 } |
|
312 |
|
313 /*! |
|
314 Returns which performance hint is set for the QStaticText. |
|
315 |
|
316 \sa setPerformanceHint() |
|
317 */ |
|
318 QStaticText::PerformanceHint QStaticText::performanceHint() const |
|
319 { |
|
320 return data->useBackendOptimizations ? AggressiveCaching : ModerateCaching; |
|
321 } |
|
322 |
|
323 /*! |
|
324 Sets the preferred width for this QStaticText. If the text is wider than the specified width, |
|
325 it will be broken into multiple lines and grow vertically. If the text cannot be split into |
|
326 multiple lines, it will be larger than the specified \a textWidth. |
|
327 |
|
328 Setting the preferred text width to a negative number will cause the text to be unbounded. |
|
329 |
|
330 Use size() to get the actual size of the text. |
|
331 |
|
332 \note This function will cause the layout of the text to require recalculation. |
|
333 |
|
334 \sa textWidth(), size() |
|
335 */ |
|
336 void QStaticText::setTextWidth(qreal textWidth) |
|
337 { |
|
338 detach(); |
|
339 data->textWidth = textWidth; |
|
340 data->invalidate(); |
|
341 } |
|
342 |
|
343 /*! |
|
344 Returns the preferred width for this QStaticText. |
|
345 |
|
346 \sa setTextWidth() |
|
347 */ |
|
348 qreal QStaticText::textWidth() const |
|
349 { |
|
350 return data->textWidth; |
|
351 } |
|
352 |
|
353 /*! |
|
354 Returns the size of the bounding rect for this QStaticText. |
|
355 |
|
356 \sa textWidth() |
|
357 */ |
|
358 QSizeF QStaticText::size() const |
|
359 { |
|
360 if (data->needsRelayout) |
|
361 data->init(); |
|
362 return data->actualSize; |
|
363 } |
|
364 |
|
365 QStaticTextPrivate::QStaticTextPrivate() |
|
366 : textWidth(-1.0), items(0), itemCount(0), glyphPool(0), positionPool(0), |
|
367 needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText) |
|
368 { |
|
369 } |
|
370 |
|
371 QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other) |
|
372 : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix), |
|
373 items(0), itemCount(0), glyphPool(0), positionPool(0), needsRelayout(true), |
|
374 useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat) |
|
375 { |
|
376 } |
|
377 |
|
378 QStaticTextPrivate::~QStaticTextPrivate() |
|
379 { |
|
380 delete[] items; |
|
381 delete[] glyphPool; |
|
382 delete[] positionPool; |
|
383 } |
|
384 |
|
385 QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q) |
|
386 { |
|
387 return q->data.data(); |
|
388 } |
|
389 |
|
390 Q_GUI_EXPORT extern int qt_defaultDpiX(); |
|
391 Q_GUI_EXPORT extern int qt_defaultDpiY(); |
|
392 |
|
393 namespace { |
|
394 |
|
395 class DrawTextItemRecorder: public QPaintEngine |
|
396 { |
|
397 public: |
|
398 DrawTextItemRecorder(int expectedItemCount, QStaticTextItem *items, |
|
399 int expectedGlyphCount, QFixedPoint *positionPool, glyph_t *glyphPool) |
|
400 : m_items(items), |
|
401 m_itemCount(0), m_glyphCount(0), |
|
402 m_expectedItemCount(expectedItemCount), |
|
403 m_expectedGlyphCount(expectedGlyphCount), |
|
404 m_glyphPool(glyphPool), |
|
405 m_positionPool(positionPool), |
|
406 m_dirtyPen(false) |
|
407 { |
|
408 } |
|
409 |
|
410 virtual void updateState(const QPaintEngineState &newState) |
|
411 { |
|
412 if (newState.state() & QPaintEngine::DirtyPen) |
|
413 m_dirtyPen = true; |
|
414 } |
|
415 |
|
416 virtual void drawTextItem(const QPointF &position, const QTextItem &textItem) |
|
417 { |
|
418 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); |
|
419 |
|
420 m_itemCount++; |
|
421 m_glyphCount += ti.glyphs.numGlyphs; |
|
422 if (m_items == 0) |
|
423 return; |
|
424 |
|
425 Q_ASSERT(m_itemCount <= m_expectedItemCount); |
|
426 Q_ASSERT(m_glyphCount <= m_expectedGlyphCount); |
|
427 |
|
428 QStaticTextItem *currentItem = (m_items + (m_itemCount - 1)); |
|
429 currentItem->fontEngine = ti.fontEngine; |
|
430 currentItem->font = ti.font(); |
|
431 currentItem->chars = ti.chars; |
|
432 currentItem->numChars = ti.num_chars; |
|
433 currentItem->numGlyphs = ti.glyphs.numGlyphs; |
|
434 currentItem->glyphs = m_glyphPool; |
|
435 currentItem->glyphPositions = m_positionPool; |
|
436 if (m_dirtyPen) |
|
437 currentItem->color = state->pen().color(); |
|
438 |
|
439 QTransform matrix = state->transform(); |
|
440 matrix.translate(position.x(), position.y()); |
|
441 |
|
442 QVarLengthArray<glyph_t> glyphs; |
|
443 QVarLengthArray<QFixedPoint> positions; |
|
444 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); |
|
445 |
|
446 int size = glyphs.size(); |
|
447 Q_ASSERT(size == ti.glyphs.numGlyphs); |
|
448 Q_ASSERT(size == positions.size()); |
|
449 |
|
450 memmove(currentItem->glyphs, glyphs.constData(), sizeof(glyph_t) * size); |
|
451 memmove(currentItem->glyphPositions, positions.constData(), sizeof(QFixedPoint) * size); |
|
452 |
|
453 m_glyphPool += size; |
|
454 m_positionPool += size; |
|
455 } |
|
456 |
|
457 |
|
458 virtual bool begin(QPaintDevice *) { return true; } |
|
459 virtual bool end() { return true; } |
|
460 virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {} |
|
461 virtual Type type() const |
|
462 { |
|
463 return User; |
|
464 } |
|
465 |
|
466 int itemCount() const |
|
467 { |
|
468 return m_itemCount; |
|
469 } |
|
470 |
|
471 int glyphCount() const |
|
472 { |
|
473 return m_glyphCount; |
|
474 } |
|
475 |
|
476 private: |
|
477 QStaticTextItem *m_items; |
|
478 int m_itemCount; |
|
479 int m_glyphCount; |
|
480 int m_expectedItemCount; |
|
481 int m_expectedGlyphCount; |
|
482 |
|
483 glyph_t *m_glyphPool; |
|
484 QFixedPoint *m_positionPool; |
|
485 |
|
486 bool m_dirtyPen; |
|
487 }; |
|
488 |
|
489 class DrawTextItemDevice: public QPaintDevice |
|
490 { |
|
491 public: |
|
492 DrawTextItemDevice(int expectedItemCount = -1, QStaticTextItem *items = 0, |
|
493 int expectedGlyphCount = -1, QFixedPoint *positionPool = 0, |
|
494 glyph_t *glyphPool = 0) |
|
495 { |
|
496 m_paintEngine = new DrawTextItemRecorder(expectedItemCount, items, |
|
497 expectedGlyphCount, positionPool, glyphPool); |
|
498 } |
|
499 |
|
500 ~DrawTextItemDevice() |
|
501 { |
|
502 delete m_paintEngine; |
|
503 } |
|
504 |
|
505 int metric(PaintDeviceMetric m) const |
|
506 { |
|
507 int val; |
|
508 switch (m) { |
|
509 case PdmWidth: |
|
510 case PdmHeight: |
|
511 case PdmWidthMM: |
|
512 case PdmHeightMM: |
|
513 val = 0; |
|
514 break; |
|
515 case PdmDpiX: |
|
516 case PdmPhysicalDpiX: |
|
517 val = qt_defaultDpiX(); |
|
518 break; |
|
519 case PdmDpiY: |
|
520 case PdmPhysicalDpiY: |
|
521 val = qt_defaultDpiY(); |
|
522 break; |
|
523 case PdmNumColors: |
|
524 val = 16777216; |
|
525 break; |
|
526 case PdmDepth: |
|
527 val = 24; |
|
528 break; |
|
529 default: |
|
530 val = 0; |
|
531 qWarning("DrawTextItemDevice::metric: Invalid metric command"); |
|
532 } |
|
533 return val; |
|
534 } |
|
535 |
|
536 virtual QPaintEngine *paintEngine() const |
|
537 { |
|
538 return m_paintEngine; |
|
539 } |
|
540 |
|
541 int itemCount() const |
|
542 { |
|
543 return m_paintEngine->itemCount(); |
|
544 } |
|
545 |
|
546 int glyphCount() const |
|
547 { |
|
548 return m_paintEngine->glyphCount(); |
|
549 } |
|
550 |
|
551 private: |
|
552 DrawTextItemRecorder *m_paintEngine; |
|
553 }; |
|
554 } |
|
555 |
|
556 void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p) |
|
557 { |
|
558 bool preferRichText = textFormat == Qt::RichText |
|
559 || (textFormat == Qt::AutoText && Qt::mightBeRichText(text)); |
|
560 |
|
561 if (!preferRichText) { |
|
562 QTextLayout textLayout; |
|
563 textLayout.setText(text); |
|
564 textLayout.setFont(font); |
|
565 |
|
566 qreal leading = QFontMetricsF(font).leading(); |
|
567 qreal height = -leading; |
|
568 |
|
569 textLayout.beginLayout(); |
|
570 while (1) { |
|
571 QTextLine line = textLayout.createLine(); |
|
572 if (!line.isValid()) |
|
573 break; |
|
574 |
|
575 if (textWidth >= 0.0) |
|
576 line.setLineWidth(textWidth); |
|
577 height += leading; |
|
578 line.setPosition(QPointF(0.0, height)); |
|
579 height += line.height(); |
|
580 } |
|
581 textLayout.endLayout(); |
|
582 |
|
583 actualSize = textLayout.boundingRect().size(); |
|
584 textLayout.draw(p, topLeftPosition); |
|
585 } else { |
|
586 QTextDocument document; |
|
587 #ifndef QT_NO_CSSPARSER |
|
588 QColor color = p->pen().color(); |
|
589 document.setDefaultStyleSheet(QString::fromLatin1("body { color: #%1%2%3 }") |
|
590 .arg(QString::number(color.red(), 16), 2, QLatin1Char('0')) |
|
591 .arg(QString::number(color.green(), 16), 2, QLatin1Char('0')) |
|
592 .arg(QString::number(color.blue(), 16), 2, QLatin1Char('0'))); |
|
593 #endif |
|
594 document.setDefaultFont(font); |
|
595 document.setDocumentMargin(0.0); |
|
596 if (textWidth >= 0.0) |
|
597 document.setTextWidth(textWidth); |
|
598 #ifndef QT_NO_TEXTHTMLPARSER |
|
599 document.setHtml(text); |
|
600 #else |
|
601 document.setPlainText(text); |
|
602 #endif |
|
603 |
|
604 document.adjustSize(); |
|
605 p->save(); |
|
606 p->translate(topLeftPosition); |
|
607 document.drawContents(p); |
|
608 p->restore(); |
|
609 |
|
610 actualSize = document.size(); |
|
611 } |
|
612 } |
|
613 |
|
614 void QStaticTextPrivate::init() |
|
615 { |
|
616 delete[] items; |
|
617 delete[] glyphPool; |
|
618 delete[] positionPool; |
|
619 |
|
620 position = QPointF(0, 0); |
|
621 |
|
622 // Draw once to count number of items and glyphs, so that we can use as little memory |
|
623 // as possible to store the data |
|
624 DrawTextItemDevice counterDevice; |
|
625 { |
|
626 QPainter painter(&counterDevice); |
|
627 painter.setFont(font); |
|
628 painter.setTransform(matrix); |
|
629 |
|
630 paintText(QPointF(0, 0), &painter); |
|
631 |
|
632 } |
|
633 |
|
634 itemCount = counterDevice.itemCount(); |
|
635 items = new QStaticTextItem[itemCount]; |
|
636 |
|
637 if (useBackendOptimizations) { |
|
638 for (int i=0; i<itemCount; ++i) |
|
639 items[i].useBackendOptimizations = true; |
|
640 } |
|
641 |
|
642 |
|
643 int glyphCount = counterDevice.glyphCount(); |
|
644 glyphPool = new glyph_t[glyphCount]; |
|
645 positionPool = new QFixedPoint[glyphCount]; |
|
646 |
|
647 // Draw again to actually record the items and glyphs |
|
648 DrawTextItemDevice recorderDevice(itemCount, items, glyphCount, positionPool, glyphPool); |
|
649 { |
|
650 QPainter painter(&recorderDevice); |
|
651 painter.setFont(font); |
|
652 painter.setTransform(matrix); |
|
653 |
|
654 paintText(QPointF(0, 0), &painter); |
|
655 } |
|
656 |
|
657 needsRelayout = false; |
|
658 } |
|
659 |
|
660 QT_END_NAMESPACE |