1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
41 #include "qpaintengine.h"
42 #include "qpaintengine_p.h"
43 #include "qpainter_p.h"
46 #include "qapplication.h"
49 #include <private/qtextengine_p.h>
50 #include <qvarlengtharray.h>
51 #include <private/qfontengine_p.h>
52 #include <private/qpaintengineex_p.h>
60 \brief The QTextItem class provides all the information required to draw
61 text in a custom paint engine.
63 When you reimplement your own paint engine, you must reimplement
64 QPaintEngine::drawTextItem(), a function that takes a QTextItem as
69 \enum QTextItem::RenderFlag
71 \value RightToLeft Render the text from right to left.
72 \value Overline Paint a line above the text.
73 \value Underline Paint a line under the text.
74 \value StrikeOut Paint a line through the text.
80 \fn qreal QTextItem::descent() const
82 Corresponds to the \l{QFontMetrics::descent()}{descent} of the piece of text that is drawn.
84 qreal QTextItem::descent() const
86 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
87 return ti->descent.toReal();
91 \fn qreal QTextItem::ascent() const
93 Corresponds to the \l{QFontMetrics::ascent()}{ascent} of the piece of text that is drawn.
95 qreal QTextItem::ascent() const
97 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
98 return ti->ascent.toReal();
102 \fn qreal QTextItem::width() const
104 Specifies the total width of the text to be drawn.
106 qreal QTextItem::width() const
108 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
109 return ti->width.toReal();
113 \fn QTextItem::RenderFlags QTextItem::renderFlags() const
115 Returns the render flags used.
117 QTextItem::RenderFlags QTextItem::renderFlags() const
119 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
124 \fn QString QTextItem::text() const
126 Returns the text that should be drawn.
128 QString QTextItem::text() const
130 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
131 return QString(ti->chars, ti->num_chars);
135 \fn QFont QTextItem::font() const
137 Returns the font that should be used to draw the text.
139 QFont QTextItem::font() const
141 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
142 return ti->f ? *ti->f : QApplication::font();
150 \brief The QPaintEngine class provides an abstract definition of how
151 QPainter draws to a given device on a given platform.
153 Qt 4.0 provides several premade implementations of QPaintEngine for the
154 different painter backends we support. We provide one paint engine for each
155 window system and painting framework we support. This includes X11 on
156 Unix/Linux and CoreGraphics on Mac OS X. In addition we provide QPaintEngine
157 implementations for OpenGL (accessible through QGLWidget) and PostScript
158 (accessible through QPSPrinter on X11). Additionally there is a raster-based
159 paint engine that is a fallback for when an engine does not support a certain
162 If one wants to use QPainter to draw to a different backend,
163 one must subclass QPaintEngine and reimplement all its virtual
164 functions. The QPaintEngine implementation is then made available by
165 subclassing QPaintDevice and reimplementing the virtual function
166 QPaintDevice::paintEngine().
168 QPaintEngine is created and owned by the QPaintDevice that created it.
170 The big advantage of the QPaintEngine approach opposed to
171 Qt 3's QPainter/QPaintDevice::cmd() approach is that it is now
172 possible to adapt to multiple technologies on each platform and take
173 advantage of each to the fullest.
175 \sa QPainter, QPaintDevice::paintEngine(), {Paint System}
179 \enum QPaintEngine::PaintEngineFeature
181 This enum is used to describe the features or capabilities that the
182 paint engine has. If a feature is not supported by the engine,
183 QPainter will do a best effort to emulate that feature through other
184 means and pass on an alpha blended QImage to the engine with the
185 emulated results. Some features cannot be emulated: AlphaBlend and PorterDuff.
187 \value AlphaBlend The engine can alpha blend primitives.
188 \value Antialiasing The engine can use antialising to improve the appearance
189 of rendered primitives.
190 \value BlendModes The engine supports blending modes.
191 \value BrushStroke The engine supports drawing strokes that
192 contain brushes as fills, not just solid
193 colors (e.g. a dashed gradient line of
195 \value ConicalGradientFill The engine supports conical gradient fills.
196 \value ConstantOpacity The engine supports the feature provided by
197 QPainter::setOpacity().
198 \value LinearGradientFill The engine supports linear gradient fills.
199 \value MaskedBrush The engine is capable of rendering brushes that has a
200 texture with an alpha channel or a mask.
201 \value ObjectBoundingModeGradients The engine has native support for gradients
202 with coordinate mode QGradient::ObjectBoundingMode.
203 Otherwise, if QPaintEngine::PatternTransform is
204 supported, object bounding mode gradients are
205 converted to gradients with coordinate mode
206 QGradient::LogicalMode and a brush transform for
207 the coordinate mapping.
208 \value PainterPaths The engine has path support.
209 \value PaintOutsidePaintEvent The engine is capable of painting outside of
211 \value PatternBrush The engine is capable of rendering brushes with
212 the brush patterns specified in Qt::BrushStyle.
213 \value PatternTransform The engine has support for transforming brush
215 \value PerspectiveTransform The engine has support for performing perspective
216 transformations on primitives.
217 \value PixmapTransform The engine can transform pixmaps, including
218 rotation and shearing.
219 \value PorterDuff The engine supports Porter-Duff operations
220 \value PrimitiveTransform The engine has support for transforming
222 \value RadialGradientFill The engine supports radial gradient fills.
223 \value RasterOpModes The engine supports bitwise raster operations.
224 \value AllFeatures All of the above features. This enum value is usually
229 \enum QPaintEngine::PolygonDrawMode
231 \value OddEvenMode The polygon should be drawn using OddEven fill
234 \value WindingMode The polygon should be drawn using Winding fill rule.
236 \value ConvexMode The polygon is a convex polygon and can be drawn
237 using specialized algorithms where available.
239 \value PolylineMode Only the outline of the polygon should be
245 \enum QPaintEngine::DirtyFlag
247 \value DirtyPen The pen is dirty and needs to be updated.
249 \value DirtyBrush The brush is dirty and needs to be updated.
251 \value DirtyBrushOrigin The brush origin is dirty and needs to
254 \value DirtyFont The font is dirty and needs to be updated.
256 \value DirtyBackground The background is dirty and needs to be
259 \value DirtyBackgroundMode The background mode is dirty and needs
262 \value DirtyTransform The transform is dirty and needs to be
265 \value DirtyClipRegion The clip region is dirty and needs to be
268 \value DirtyClipPath The clip path is dirty and needs to be
271 \value DirtyHints The render hints is dirty and needs to be
274 \value DirtyCompositionMode The composition mode is dirty and
277 \value DirtyClipEnabled Whether clipping is enabled or not is
278 dirty and needs to be updated.
280 \value DirtyOpacity The constant opacity has changed and needs to
281 be updated as part of the state change in
282 QPaintEngine::updateState().
284 \value AllDirty Convenience enum used internally.
286 These types are used by QPainter to trigger lazy updates of the
287 various states in the QPaintEngine using
288 QPaintEngine::updateState().
290 A paint engine must update every dirty state.
294 \fn void QPaintEngine::syncState()
298 Updates all dirty states in this engine. This function should ONLY
299 be used when drawing with native handles directly and immediate sync
300 from QPainters state to the native state is required.
302 void QPaintEngine::syncState()
308 static_cast<QPaintEngineEx *>(this)->sync();
311 static QPaintEngine *qt_polygon_recursion = 0;
318 \fn void QPaintEngine::drawPolygon(const QPointF *points, int pointCount,
319 PolygonDrawMode mode)
321 Reimplement this virtual function to draw the polygon defined
322 by the \a pointCount first points in \a points, using mode \a
325 \note At least one of the drawPolygon() functions must be reimplemented.
327 void QPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
329 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
330 "At least one drawPolygon function must be implemented");
331 qt_polygon_recursion = this;
332 Q_ASSERT(sizeof(QT_Point) == sizeof(QPoint));
333 QVarLengthArray<QT_Point> p(pointCount);
334 for (int i = 0; i < pointCount; ++i) {
335 p[i].x = qRound(points[i].x());
336 p[i].y = qRound(points[i].y());
338 drawPolygon((QPoint *)p.data(), pointCount, mode);
339 qt_polygon_recursion = 0;
349 Reimplement this virtual function to draw the polygon defined by the
350 \a pointCount first points in \a points, using mode \a mode.
352 \note At least one of the drawPolygon() functions must be reimplemented.
354 void QPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
356 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
357 "At least one drawPolygon function must be implemented");
358 qt_polygon_recursion = this;
359 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
360 QVarLengthArray<QT_PointF> p(pointCount);
361 for (int i=0; i<pointCount; ++i) {
362 p[i].x = points[i].x();
363 p[i].y = points[i].y();
365 drawPolygon((QPointF *)p.data(), pointCount, mode);
366 qt_polygon_recursion = 0;
370 \enum QPaintEngine::Type
375 \value CoreGraphics Mac OS X's Quartz2D (CoreGraphics)
376 \value QuickDraw Mac OS X's QuickDraw
377 \value QWindowSystem Qt for Embedded Linux
380 \value Picture QPicture format
381 \value SVG Scalable Vector Graphics XML format
383 \value Direct3D Windows only, Direct3D based engine
384 \value Pdf Portable Document Format
386 \value User First user type ID
387 \value MaxUser Last user type ID
394 \fn bool QPaintEngine::isActive() const
396 Returns true if the paint engine is actively drawing; otherwise
403 \fn void QPaintEngine::setActive(bool state)
405 Sets the active state of the paint engine to \a state.
411 \fn bool QPaintEngine::begin(QPaintDevice *pdev)
413 Reimplement this function to initialise your paint engine when
414 painting is to start on the paint device \a pdev. Return true if
415 the initialization was successful; otherwise return false.
421 \fn bool QPaintEngine::end()
423 Reimplement this function to finish painting on the current paint
424 device. Return true if painting was finished successfully;
425 otherwise return false.
427 \sa begin() isActive()
432 Draws the first \a pointCount points in the buffer \a points
434 void QPaintEngine::drawPoints(const QPointF *points, int pointCount)
436 QPainter *p = painter();
440 qreal penWidth = p->pen().widthF();
444 bool ellipses = p->pen().capStyle() == Qt::RoundCap;
448 QTransform transform;
449 if (p->pen().isCosmetic()) {
450 transform = p->transform();
451 p->setTransform(QTransform());
454 p->setBrush(p->pen().brush());
455 p->setPen(Qt::NoPen);
457 for (int i=0; i<pointCount; ++i) {
458 QPointF pos = transform.map(points[i]);
459 QRectF rect(pos.x() - penWidth / 2, pos.y() - penWidth / 2, penWidth, penWidth);
462 p->drawEllipse(rect);
472 Draws the first \a pointCount points in the buffer \a points
474 The default implementation converts the first \a pointCount QPoints in \a points
475 to QPointFs and calls the floating point version of drawPoints.
478 void QPaintEngine::drawPoints(const QPoint *points, int pointCount)
480 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
484 while (i < pointCount && i < 256) {
485 fp[i].x = points[i].x();
486 fp[i].y = points[i].y();
489 drawPoints((QPointF *)(void *)fp, i);
496 \fn void QPaintEngine::drawEllipse(const QRectF &rect)
498 Reimplement this function to draw the largest ellipse that can be
499 contained within rectangle \a rect.
501 The default implementation calls drawPolygon().
503 void QPaintEngine::drawEllipse(const QRectF &rect)
506 path.addEllipse(rect);
507 if (hasFeature(PainterPaths)) {
510 QPolygonF polygon = path.toFillPolygon();
511 drawPolygon(polygon.data(), polygon.size(), ConvexMode);
516 The default implementation of this function calls the floating
517 point version of this function
519 void QPaintEngine::drawEllipse(const QRect &rect)
521 drawEllipse(QRectF(rect));
525 \fn void QPaintEngine::drawPixmap(const QRectF &r, const QPixmap
526 &pm, const QRectF &sr)
528 Reimplement this function to draw the part of the \a pm
529 specified by the \a sr rectangle in the given \a r.
533 void qt_fill_tile(QPixmap *tile, const QPixmap &pixmap)
536 p.drawPixmap(0, 0, pixmap);
537 int x = pixmap.width();
538 while (x < tile->width()) {
539 p.drawPixmap(x, 0, *tile, 0, 0, x, pixmap.height());
542 int y = pixmap.height();
543 while (y < tile->height()) {
544 p.drawPixmap(0, y, *tile, 0, 0, tile->width(), y);
549 void qt_draw_tile(QPaintEngine *gc, qreal x, qreal y, qreal w, qreal h,
550 const QPixmap &pixmap, qreal xOffset, qreal yOffset)
552 qreal yPos, xPos, drawH, drawW, yOff, xOff;
555 while(yPos < y + h) {
556 drawH = pixmap.height() - yOff; // Cropping first row
557 if (yPos + drawH > y + h) // Cropping last row
558 drawH = y + h - yPos;
561 while(xPos < x + w) {
562 drawW = pixmap.width() - xOff; // Cropping first column
563 if (xPos + drawW > x + w) // Cropping last column
564 drawW = x + w - xPos;
565 if (drawW > 0 && drawH > 0)
566 gc->drawPixmap(QRectF(xPos, yPos, drawW, drawH), pixmap, QRectF(xOff, yOff, drawW, drawH));
577 Reimplement this function to draw the \a pixmap in the given \a
578 rect, starting at the given \a p. The pixmap will be
579 drawn repeatedly until the \a rect is filled.
581 void QPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p)
583 int sw = pixmap.width();
584 int sh = pixmap.height();
586 if (sw*sh < 8192 && sw*sh < 16*rect.width()*rect.height()) {
587 int tw = sw, th = sh;
588 while (tw*th < 32678 && tw < rect.width()/2)
590 while (tw*th < 32678 && th < rect.height()/2)
593 if (pixmap.depth() == 1) {
594 tile = QBitmap(tw, th);
596 tile = QPixmap(tw, th);
597 if (pixmap.hasAlphaChannel())
598 tile.fill(Qt::transparent);
600 qt_fill_tile(&tile, pixmap);
601 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), tile, p.x(), p.y());
603 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), pixmap, p.x(), p.y());
608 \fn void QPaintEngine::drawImage(const QRectF &rectangle, const QImage
609 &image, const QRectF &sr, Qt::ImageConversionFlags flags)
611 Reimplement this function to draw the part of the \a image
612 specified by the \a sr rectangle in the given \a rectangle using
613 the given conversion flags \a flags, to convert it to a pixmap.
616 void QPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
617 Qt::ImageConversionFlags flags)
619 QRectF baseSize(0, 0, image.width(), image.height());
622 im = im.copy(qFloor(sr.x()), qFloor(sr.y()),
623 qCeil(sr.width()), qCeil(sr.height()));
624 QPixmap pm = QPixmap::fromImage(im, flags);
625 drawPixmap(r, pm, QRectF(QPointF(0, 0), pm.size()));
629 \fn Type QPaintEngine::type() const
631 Reimplement this function to return the paint engine \l{Type}.
635 \fn void QPaintEngine::fix_neg_rect(int *x, int *y, int *w, int *h);
641 \fn bool QPaintEngine::testDirty(DirtyFlags df)
647 \fn void QPaintEngine::clearDirty(DirtyFlags df)
653 \fn void QPaintEngine::setDirty(DirtyFlags df)
659 \fn bool QPaintEngine::hasFeature(PaintEngineFeatures feature) const
661 Returns true if the paint engine supports the specified \a
662 feature; otherwise returns false.
666 \fn bool QPaintEngine::isExtended() const
670 Returns true if the paint engine is a QPaintEngineEx derivative.
674 \fn void QPaintEngine::updateState(const QPaintEngineState &state)
676 Reimplement this function to update the state of a paint engine.
678 When implemented, this function is responsible for checking the
679 paint engine's current \a state and update the properties that are
680 changed. Use the QPaintEngineState::state() function to find out
681 which properties that must be updated, then use the corresponding
682 \l {GetFunction}{get function} to retrieve the current values for
683 the given properties.
685 \sa QPaintEngineState
689 Creates a paint engine with the featureset specified by \a caps.
692 QPaintEngine::QPaintEngine(PaintEngineFeatures caps)
698 d_ptr(new QPaintEnginePrivate)
707 QPaintEngine::QPaintEngine(QPaintEnginePrivate &dptr, PaintEngineFeatures caps)
719 Destroys the paint engine.
721 QPaintEngine::~QPaintEngine()
726 Returns the paint engine's painter.
728 QPainter *QPaintEngine::painter() const
730 return state ? state->painter() : 0;
734 The default implementation ignores the \a path and does nothing.
737 void QPaintEngine::drawPath(const QPainterPath &)
739 if (hasFeature(PainterPaths)) {
740 qWarning("QPaintEngine::drawPath: Must be implemented when feature PainterPaths is set");
745 This function draws the text item \a textItem at position \a p. The
746 default implementation of this function converts the text to a
747 QPainterPath and paints the resulting path.
750 void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
752 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
756 path.setFillRule(Qt::WindingFill);
758 if (ti.glyphs.numGlyphs)
759 ti.fontEngine->addOutlineToPath(p.x(), p.y(), ti.glyphs, &path, ti.flags);
760 if (!path.isEmpty()) {
761 bool oldAA = painter()->renderHints() & QPainter::Antialiasing;
762 painter()->setRenderHint(QPainter::Antialiasing,
763 bool((painter()->renderHints() & QPainter::TextAntialiasing)
764 && !(painter()->font().styleStrategy() & QFont::NoAntialias)));
765 painter()->fillPath(path, state->pen().brush());
766 painter()->setRenderHint(QPainter::Antialiasing, oldAA);
771 The default implementation splits the list of lines in \a lines
772 into \a lineCount separate calls to drawPath() or drawPolygon()
773 depending on the feature set of the paint engine.
775 void QPaintEngine::drawLines(const QLineF *lines, int lineCount)
777 for (int i=0; i<lineCount; ++i) {
778 QPointF pts[2] = { lines[i].p1(), lines[i].p2() };
780 if (pts[0] == pts[1]) {
781 if (state->pen().capStyle() != Qt::FlatCap)
786 drawPolygon(pts, 2, PolylineMode);
793 The default implementation converts the first \a lineCount lines
794 in \a lines to a QLineF and calls the floating point version of
797 void QPaintEngine::drawLines(const QLine *lines, int lineCount)
807 Q_ASSERT(sizeof(PointF) == sizeof(QPointF));
808 Q_ASSERT(sizeof(LineF) == sizeof(QLineF));
812 while (i < lineCount && i < 256) {
813 fl[i].p1.x = lines[i].x1();
814 fl[i].p1.y = lines[i].y1();
815 fl[i].p2.x = lines[i].x2();
816 fl[i].p2.y = lines[i].y2();
819 drawLines((QLineF *)(void *)fl, i);
829 The default implementation converts the first \a rectCount
830 rectangles in the buffer \a rects to a QRectF and calls the
831 floating point version of this function.
833 void QPaintEngine::drawRects(const QRect *rects, int rectCount)
841 Q_ASSERT(sizeof(RectF) == sizeof(QRectF));
845 while (i < rectCount && i < 256) {
846 fr[i].x = rects[i].x();
847 fr[i].y = rects[i].y();
848 fr[i].w = rects[i].width();
849 fr[i].h = rects[i].height();
852 drawRects((QRectF *)(void *)fr, i);
859 Draws the first \a rectCount rectangles in the buffer \a
860 rects. The default implementation of this function calls drawPath()
861 or drawPolygon() depending on the feature set of the paint engine.
863 void QPaintEngine::drawRects(const QRectF *rects, int rectCount)
865 if (hasFeature(PainterPaths) &&
866 !state->penNeedsResolving() &&
867 !state->brushNeedsResolving()) {
868 for (int i=0; i<rectCount; ++i) {
870 path.addRect(rects[i]);
876 for (int i=0; i<rectCount; ++i) {
877 QRectF rf = rects[i];
878 QPointF pts[4] = { QPointF(rf.x(), rf.y()),
879 QPointF(rf.x() + rf.width(), rf.y()),
880 QPointF(rf.x() + rf.width(), rf.y() + rf.height()),
881 QPointF(rf.x(), rf.y() + rf.height()) };
882 drawPolygon(pts, 4, ConvexMode);
889 Sets the paintdevice that this engine operates on to \a device
891 void QPaintEngine::setPaintDevice(QPaintDevice *device)
893 d_func()->pdev = device;
897 Returns the device that this engine is painting on, if painting is
898 active; otherwise returns 0.
900 QPaintDevice *QPaintEngine::paintDevice() const
902 return d_func()->pdev;
909 Empty default implementation.
912 HDC QPaintEngine::getDC() const
921 Empty default implementation.
924 void QPaintEngine::releaseDC(HDC) const
933 Returns the offset from the painters origo to the engines
934 origo. This value is used by QPainter for engines who have
935 internal double buffering.
937 This function only makes sense when the engine is active.
939 QPoint QPaintEngine::coordinateOffset() const
947 Sets the system clip for this engine. The system clip defines the
948 basis area that the engine has to draw in. All clips that are
949 set will be be an intersection with the system clip.
951 Reset the systemclip to no clip by setting an empty region.
953 void QPaintEngine::setSystemClip(const QRegion ®ion)
956 d->systemClip = region;
957 // Be backward compatible and only call d->systemStateChanged()
958 // if we currently have a system transform/viewport set.
959 if (d->hasSystemTransform || d->hasSystemViewport) {
960 d->transformSystemClip();
961 d->systemStateChanged();
968 Returns the system clip. The system clip is read only while the
969 painter is active. An empty region indicates that system clip
973 QRegion QPaintEngine::systemClip() const
975 return d_func()->systemClip;
981 Sets the target rect for drawing within the backing store. This
982 function should ONLY be used by the backing store.
984 void QPaintEngine::setSystemRect(const QRect &rect)
987 qWarning("QPaintEngine::setSystemRect: Should not be changed while engine is active");
990 d_func()->systemRect = rect;
996 Retrieves the rect for drawing within the backing store. This
997 function should ONLY be used by the backing store.
999 QRect QPaintEngine::systemRect() const
1001 return d_func()->systemRect;
1004 void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt &ti)
1006 if (!ti.glyphs.numGlyphs)
1009 // any fixes here should probably also be done in QFontEngineBox::draw
1010 const int size = qRound(ti.fontEngine->ascent());
1011 QVarLengthArray<QFixedPoint> positions;
1012 QVarLengthArray<glyph_t> glyphs;
1013 QTransform matrix = QTransform::fromTranslate(p.x(), p.y() - size);
1014 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
1015 if (glyphs.size() == 0)
1018 QSize s(size - 3, size - 3);
1020 QPainter *painter = q_func()->state->painter();
1022 painter->setBrush(Qt::NoBrush);
1023 QPen pen = painter->pen();
1024 pen.setWidthF(ti.fontEngine->lineThickness().toReal());
1025 painter->setPen(pen);
1026 for (int k = 0; k < positions.size(); k++)
1027 painter->drawRect(QRectF(positions[k].toPointF(), s));