1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
41 #include "qpaintengine.h"
42 #include "qpaintengine_p.h"
43 #include "qpainter_p.h"
48 #include <qguiapplication.h>
49 #include <private/qtextengine_p.h>
50 #include <qvarlengtharray.h>
51 #include <private/qfontengine_p.h>
52 #include <private/qpaintengineex_p.h>
61 \brief The QTextItem class provides all the information required to draw
62 text in a custom paint engine.
64 When you reimplement your own paint engine, you must reimplement
65 QPaintEngine::drawTextItem(), a function that takes a QTextItem as
70 \enum QTextItem::RenderFlag
72 \value RightToLeft Render the text from right to left.
73 \value Overline Paint a line above the text.
74 \value Underline Paint a line under the text.
75 \value StrikeOut Paint a line through the text.
81 \fn qreal QTextItem::descent() const
83 Corresponds to the \l{QFontMetrics::descent()}{descent} of the piece of text that is drawn.
85 qreal QTextItem::descent() const
87 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
88 return ti->descent.toReal();
92 \fn qreal QTextItem::ascent() const
94 Corresponds to the \l{QFontMetrics::ascent()}{ascent} of the piece of text that is drawn.
96 qreal QTextItem::ascent() const
98 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
99 return ti->ascent.toReal();
103 \fn qreal QTextItem::width() const
105 Specifies the total width of the text to be drawn.
107 qreal QTextItem::width() const
109 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
110 return ti->width.toReal();
114 \fn QTextItem::RenderFlags QTextItem::renderFlags() const
116 Returns the render flags used.
118 QTextItem::RenderFlags QTextItem::renderFlags() const
120 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
125 \fn QString QTextItem::text() const
127 Returns the text that should be drawn.
129 QString QTextItem::text() const
131 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
132 return QString(ti->chars, ti->num_chars);
136 \fn QFont QTextItem::font() const
138 Returns the font that should be used to draw the text.
140 QFont QTextItem::font() const
142 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
143 return ti->f ? *ti->f : QGuiApplication::font();
152 \brief The QPaintEngine class provides an abstract definition of how
153 QPainter draws to a given device on a given platform.
155 Qt provides several premade implementations of QPaintEngine for the
156 different painter backends we support. The primary paint engine
157 provided is the raster paint engine, which contains a software
158 rasterizer which supports the full feature set on all supported platforms.
159 This is the default for painting on QWidget-based classes in e.g. on Windows,
160 X11 and Mac OS X, it is the backend for painting on QImage and it is
161 used as a fallback for paint engines that do not support a certain
162 capability. In addition we provide QPaintEngine implementations for
163 OpenGL (accessible through QGLWidget) and printing (which allows using
164 QPainter to draw on a QPrinter object).
166 If one wants to use QPainter to draw to a different backend,
167 one must subclass QPaintEngine and reimplement all its virtual
168 functions. The QPaintEngine implementation is then made available by
169 subclassing QPaintDevice and reimplementing the virtual function
170 QPaintDevice::paintEngine().
172 QPaintEngine is created and owned by the QPaintDevice that created it.
174 \sa QPainter, QPaintDevice::paintEngine(), {Paint System}
178 \enum QPaintEngine::PaintEngineFeature
180 This enum is used to describe the features or capabilities that the
181 paint engine has. If a feature is not supported by the engine,
182 QPainter will do a best effort to emulate that feature through other
183 means and pass on an alpha blended QImage to the engine with the
184 emulated results. Some features cannot be emulated: AlphaBlend and PorterDuff.
186 \value AlphaBlend The engine can alpha blend primitives.
187 \value Antialiasing The engine can use antialising to improve the appearance
188 of rendered primitives.
189 \value BlendModes The engine supports blending modes.
190 \value BrushStroke The engine supports drawing strokes that
191 contain brushes as fills, not just solid
192 colors (e.g. a dashed gradient line of
194 \value ConicalGradientFill The engine supports conical gradient fills.
195 \value ConstantOpacity The engine supports the feature provided by
196 QPainter::setOpacity().
197 \value LinearGradientFill The engine supports linear gradient fills.
198 \value MaskedBrush The engine is capable of rendering brushes that has a
199 texture with an alpha channel or a mask.
200 \value ObjectBoundingModeGradients The engine has native support for gradients
201 with coordinate mode QGradient::ObjectBoundingMode.
202 Otherwise, if QPaintEngine::PatternTransform is
203 supported, object bounding mode gradients are
204 converted to gradients with coordinate mode
205 QGradient::LogicalMode and a brush transform for
206 the coordinate mapping.
207 \value PainterPaths The engine has path support.
208 \value PaintOutsidePaintEvent The engine is capable of painting outside of
210 \value PatternBrush The engine is capable of rendering brushes with
211 the brush patterns specified in Qt::BrushStyle.
212 \value PatternTransform The engine has support for transforming brush
214 \value PerspectiveTransform The engine has support for performing perspective
215 transformations on primitives.
216 \value PixmapTransform The engine can transform pixmaps, including
217 rotation and shearing.
218 \value PorterDuff The engine supports Porter-Duff operations
219 \value PrimitiveTransform The engine has support for transforming
221 \value RadialGradientFill The engine supports radial gradient fills.
222 \value RasterOpModes The engine supports bitwise raster operations.
223 \value AllFeatures All of the above features. This enum value is usually
228 \enum QPaintEngine::PolygonDrawMode
230 \value OddEvenMode The polygon should be drawn using OddEven fill
233 \value WindingMode The polygon should be drawn using Winding fill rule.
235 \value ConvexMode The polygon is a convex polygon and can be drawn
236 using specialized algorithms where available.
238 \value PolylineMode Only the outline of the polygon should be
244 \enum QPaintEngine::DirtyFlag
246 \value DirtyPen The pen is dirty and needs to be updated.
248 \value DirtyBrush The brush is dirty and needs to be updated.
250 \value DirtyBrushOrigin The brush origin is dirty and needs to
253 \value DirtyFont The font is dirty and needs to be updated.
255 \value DirtyBackground The background is dirty and needs to be
258 \value DirtyBackgroundMode The background mode is dirty and needs
261 \value DirtyTransform The transform is dirty and needs to be
264 \value DirtyClipRegion The clip region is dirty and needs to be
267 \value DirtyClipPath The clip path is dirty and needs to be
270 \value DirtyHints The render hints is dirty and needs to be
273 \value DirtyCompositionMode The composition mode is dirty and
276 \value DirtyClipEnabled Whether clipping is enabled or not is
277 dirty and needs to be updated.
279 \value DirtyOpacity The constant opacity has changed and needs to
280 be updated as part of the state change in
281 QPaintEngine::updateState().
283 \value AllDirty Convenience enum used internally.
285 These types are used by QPainter to trigger lazy updates of the
286 various states in the QPaintEngine using
287 QPaintEngine::updateState().
289 A paint engine must update every dirty state.
293 \fn void QPaintEngine::syncState()
297 Updates all dirty states in this engine. This function should ONLY
298 be used when drawing with native handles directly and immediate sync
299 from QPainters state to the native state is required.
301 void QPaintEngine::syncState()
307 static_cast<QPaintEngineEx *>(this)->sync();
310 static QPaintEngine *qt_polygon_recursion = 0;
317 \fn void QPaintEngine::drawPolygon(const QPointF *points, int pointCount,
318 PolygonDrawMode mode)
320 Reimplement this virtual function to draw the polygon defined
321 by the \a pointCount first points in \a points, using mode \a
324 \note At least one of the drawPolygon() functions must be reimplemented.
326 void QPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
328 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
329 "At least one drawPolygon function must be implemented");
330 qt_polygon_recursion = this;
331 Q_ASSERT(sizeof(QT_Point) == sizeof(QPoint));
332 QVarLengthArray<QT_Point> p(pointCount);
333 for (int i = 0; i < pointCount; ++i) {
334 p[i].x = qRound(points[i].x());
335 p[i].y = qRound(points[i].y());
337 drawPolygon((QPoint *)p.data(), pointCount, mode);
338 qt_polygon_recursion = 0;
348 Reimplement this virtual function to draw the polygon defined by the
349 \a pointCount first points in \a points, using mode \a mode.
351 \note At least one of the drawPolygon() functions must be reimplemented.
353 void QPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
355 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
356 "At least one drawPolygon function must be implemented");
357 qt_polygon_recursion = this;
358 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
359 QVarLengthArray<QT_PointF> p(pointCount);
360 for (int i=0; i<pointCount; ++i) {
361 p[i].x = points[i].x();
362 p[i].y = points[i].y();
364 drawPolygon((QPointF *)p.data(), pointCount, mode);
365 qt_polygon_recursion = 0;
369 \enum QPaintEngine::Type
374 \value CoreGraphics Mac OS X's Quartz2D (CoreGraphics)
375 \value QuickDraw Mac OS X's QuickDraw
376 \value QWindowSystem Qt for Embedded Linux
379 \value Picture QPicture format
380 \value SVG Scalable Vector Graphics XML format
382 \value Direct3D Windows only, Direct3D based engine
383 \value Pdf Portable Document Format
385 \value User First user type ID
386 \value MaxUser Last user type ID
393 \fn bool QPaintEngine::isActive() const
395 Returns true if the paint engine is actively drawing; otherwise
402 \fn void QPaintEngine::setActive(bool state)
404 Sets the active state of the paint engine to \a state.
410 \fn bool QPaintEngine::begin(QPaintDevice *pdev)
412 Reimplement this function to initialise your paint engine when
413 painting is to start on the paint device \a pdev. Return true if
414 the initialization was successful; otherwise return false.
416 \sa end(), isActive()
420 \fn bool QPaintEngine::end()
422 Reimplement this function to finish painting on the current paint
423 device. Return true if painting was finished successfully;
424 otherwise return false.
426 \sa begin(), isActive()
431 Draws the first \a pointCount points in the buffer \a points
433 void QPaintEngine::drawPoints(const QPointF *points, int pointCount)
435 QPainter *p = painter();
439 qreal penWidth = p->pen().widthF();
443 bool ellipses = p->pen().capStyle() == Qt::RoundCap;
447 QTransform transform;
448 if (qt_pen_is_cosmetic(p->pen(), p->renderHints())) {
449 transform = p->transform();
450 p->setTransform(QTransform());
453 p->setBrush(p->pen().brush());
454 p->setPen(Qt::NoPen);
456 for (int i=0; i<pointCount; ++i) {
457 QPointF pos = transform.map(points[i]);
458 QRectF rect(pos.x() - penWidth / 2, pos.y() - penWidth / 2, penWidth, penWidth);
461 p->drawEllipse(rect);
471 Draws the first \a pointCount points in the buffer \a points
473 The default implementation converts the first \a pointCount QPoints in \a points
474 to QPointFs and calls the floating point version of drawPoints.
477 void QPaintEngine::drawPoints(const QPoint *points, int pointCount)
479 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
483 while (i < pointCount && i < 256) {
484 fp[i].x = points[i].x();
485 fp[i].y = points[i].y();
488 drawPoints((QPointF *)(void *)fp, i);
495 \fn void QPaintEngine::drawEllipse(const QRectF &rect)
497 Reimplement this function to draw the largest ellipse that can be
498 contained within rectangle \a rect.
500 The default implementation calls drawPolygon().
502 void QPaintEngine::drawEllipse(const QRectF &rect)
505 path.addEllipse(rect);
506 if (hasFeature(PainterPaths)) {
509 QPolygonF polygon = path.toFillPolygon();
510 drawPolygon(polygon.data(), polygon.size(), ConvexMode);
515 The default implementation of this function calls the floating
516 point version of this function
518 void QPaintEngine::drawEllipse(const QRect &rect)
520 drawEllipse(QRectF(rect));
524 \fn void QPaintEngine::drawPixmap(const QRectF &r, const QPixmap
525 &pm, const QRectF &sr)
527 Reimplement this function to draw the part of the \a pm
528 specified by the \a sr rectangle in the given \a r.
532 void qt_fill_tile(QPixmap *tile, const QPixmap &pixmap)
535 p.drawPixmap(0, 0, pixmap);
536 int x = pixmap.width();
537 while (x < tile->width()) {
538 p.drawPixmap(x, 0, *tile, 0, 0, x, pixmap.height());
541 int y = pixmap.height();
542 while (y < tile->height()) {
543 p.drawPixmap(0, y, *tile, 0, 0, tile->width(), y);
548 void qt_draw_tile(QPaintEngine *gc, qreal x, qreal y, qreal w, qreal h,
549 const QPixmap &pixmap, qreal xOffset, qreal yOffset)
551 qreal yPos, xPos, drawH, drawW, yOff, xOff;
554 while(yPos < y + h) {
555 drawH = pixmap.height() - yOff; // Cropping first row
556 if (yPos + drawH > y + h) // Cropping last row
557 drawH = y + h - yPos;
560 while(xPos < x + w) {
561 drawW = pixmap.width() - xOff; // Cropping first column
562 if (xPos + drawW > x + w) // Cropping last column
563 drawW = x + w - xPos;
564 if (drawW > 0 && drawH > 0)
565 gc->drawPixmap(QRectF(xPos, yPos, drawW, drawH), pixmap, QRectF(xOff, yOff, drawW, drawH));
576 Reimplement this function to draw the \a pixmap in the given \a
577 rect, starting at the given \a p. The pixmap will be
578 drawn repeatedly until the \a rect is filled.
580 void QPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p)
582 int sw = pixmap.width();
583 int sh = pixmap.height();
585 if (sw*sh < 8192 && sw*sh < 16*rect.width()*rect.height()) {
586 int tw = sw, th = sh;
587 while (tw*th < 32678 && tw < rect.width()/2)
589 while (tw*th < 32678 && th < rect.height()/2)
592 if (pixmap.depth() == 1) {
593 tile = QBitmap(tw, th);
595 tile = QPixmap(tw, th);
596 if (pixmap.hasAlphaChannel())
597 tile.fill(Qt::transparent);
599 qt_fill_tile(&tile, pixmap);
600 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), tile, p.x(), p.y());
602 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), pixmap, p.x(), p.y());
607 \fn void QPaintEngine::drawImage(const QRectF &rectangle, const QImage
608 &image, const QRectF &sr, Qt::ImageConversionFlags flags)
610 Reimplement this function to draw the part of the \a image
611 specified by the \a sr rectangle in the given \a rectangle using
612 the given conversion flags \a flags, to convert it to a pixmap.
615 void QPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
616 Qt::ImageConversionFlags flags)
618 QRectF baseSize(0, 0, image.width(), image.height());
621 im = im.copy(qFloor(sr.x()), qFloor(sr.y()),
622 qCeil(sr.width()), qCeil(sr.height()));
623 QPixmap pm = QPixmap::fromImage(im, flags);
624 drawPixmap(r, pm, QRectF(QPointF(0, 0), pm.size()));
628 \fn Type QPaintEngine::type() const
630 Reimplement this function to return the paint engine \l{Type}.
634 \fn void QPaintEngine::fix_neg_rect(int *x, int *y, int *w, int *h);
640 \fn bool QPaintEngine::testDirty(DirtyFlags df)
646 \fn void QPaintEngine::clearDirty(DirtyFlags df)
652 \fn void QPaintEngine::setDirty(DirtyFlags df)
658 \fn bool QPaintEngine::hasFeature(PaintEngineFeatures feature) const
660 Returns true if the paint engine supports the specified \a
661 feature; otherwise returns false.
665 \fn bool QPaintEngine::isExtended() const
669 Returns true if the paint engine is a QPaintEngineEx derivative.
673 \fn void QPaintEngine::updateState(const QPaintEngineState &state)
675 Reimplement this function to update the state of a paint engine.
677 When implemented, this function is responsible for checking the
678 paint engine's current \a state and update the properties that are
679 changed. Use the QPaintEngineState::state() function to find out
680 which properties that must be updated, then use the corresponding
681 \l {GetFunction}{get function} to retrieve the current values for
682 the given properties.
684 \sa QPaintEngineState
688 Creates a paint engine with the featureset specified by \a caps.
691 QPaintEngine::QPaintEngine(PaintEngineFeatures caps)
697 d_ptr(new QPaintEnginePrivate)
706 QPaintEngine::QPaintEngine(QPaintEnginePrivate &dptr, PaintEngineFeatures caps)
718 Destroys the paint engine.
720 QPaintEngine::~QPaintEngine()
725 Returns the paint engine's painter.
727 QPainter *QPaintEngine::painter() const
729 return state ? state->painter() : 0;
733 The default implementation ignores the \a path and does nothing.
736 void QPaintEngine::drawPath(const QPainterPath &)
738 if (hasFeature(PainterPaths)) {
739 qWarning("QPaintEngine::drawPath: Must be implemented when feature PainterPaths is set");
744 This function draws the text item \a textItem at position \a p. The
745 default implementation of this function converts the text to a
746 QPainterPath and paints the resulting path.
749 void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
751 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
754 path.setFillRule(Qt::WindingFill);
755 if (ti.glyphs.numGlyphs)
756 ti.fontEngine->addOutlineToPath(0, 0, ti.glyphs, &path, ti.flags);
757 if (!path.isEmpty()) {
759 painter()->setRenderHint(QPainter::Antialiasing,
760 bool((painter()->renderHints() & QPainter::TextAntialiasing)
761 && !(painter()->font().styleStrategy() & QFont::NoAntialias)));
762 painter()->translate(p.x(), p.y());
763 painter()->fillPath(path, state->pen().brush());
764 painter()->restore();
769 The default implementation splits the list of lines in \a lines
770 into \a lineCount separate calls to drawPath() or drawPolygon()
771 depending on the feature set of the paint engine.
773 void QPaintEngine::drawLines(const QLineF *lines, int lineCount)
775 for (int i=0; i<lineCount; ++i) {
776 QPointF pts[2] = { lines[i].p1(), lines[i].p2() };
778 if (pts[0] == pts[1]) {
779 if (state->pen().capStyle() != Qt::FlatCap)
784 drawPolygon(pts, 2, PolylineMode);
791 The default implementation converts the first \a lineCount lines
792 in \a lines to a QLineF and calls the floating point version of
795 void QPaintEngine::drawLines(const QLine *lines, int lineCount)
805 Q_ASSERT(sizeof(PointF) == sizeof(QPointF));
806 Q_ASSERT(sizeof(LineF) == sizeof(QLineF));
810 while (i < lineCount && i < 256) {
811 fl[i].p1.x = lines[i].x1();
812 fl[i].p1.y = lines[i].y1();
813 fl[i].p2.x = lines[i].x2();
814 fl[i].p2.y = lines[i].y2();
817 drawLines((QLineF *)(void *)fl, i);
827 The default implementation converts the first \a rectCount
828 rectangles in the buffer \a rects to a QRectF and calls the
829 floating point version of this function.
831 void QPaintEngine::drawRects(const QRect *rects, int rectCount)
839 Q_ASSERT(sizeof(RectF) == sizeof(QRectF));
843 while (i < rectCount && i < 256) {
844 fr[i].x = rects[i].x();
845 fr[i].y = rects[i].y();
846 fr[i].w = rects[i].width();
847 fr[i].h = rects[i].height();
850 drawRects((QRectF *)(void *)fr, i);
857 Draws the first \a rectCount rectangles in the buffer \a
858 rects. The default implementation of this function calls drawPath()
859 or drawPolygon() depending on the feature set of the paint engine.
861 void QPaintEngine::drawRects(const QRectF *rects, int rectCount)
863 if (hasFeature(PainterPaths) &&
864 !state->penNeedsResolving() &&
865 !state->brushNeedsResolving()) {
866 for (int i=0; i<rectCount; ++i) {
868 path.addRect(rects[i]);
874 for (int i=0; i<rectCount; ++i) {
875 QRectF rf = rects[i];
876 QPointF pts[4] = { QPointF(rf.x(), rf.y()),
877 QPointF(rf.x() + rf.width(), rf.y()),
878 QPointF(rf.x() + rf.width(), rf.y() + rf.height()),
879 QPointF(rf.x(), rf.y() + rf.height()) };
880 drawPolygon(pts, 4, ConvexMode);
887 Sets the paintdevice that this engine operates on to \a device
889 void QPaintEngine::setPaintDevice(QPaintDevice *device)
891 d_func()->pdev = device;
895 Returns the device that this engine is painting on, if painting is
896 active; otherwise returns 0.
898 QPaintDevice *QPaintEngine::paintDevice() const
900 return d_func()->pdev;
907 Returns the offset from the painters origo to the engines
908 origo. This value is used by QPainter for engines who have
909 internal double buffering.
911 This function only makes sense when the engine is active.
913 QPoint QPaintEngine::coordinateOffset() const
921 Sets the system clip for this engine. The system clip defines the
922 basis area that the engine has to draw in. All clips that are
923 set will be an intersection with the system clip.
925 Reset the systemclip to no clip by setting an empty region.
927 void QPaintEngine::setSystemClip(const QRegion ®ion)
930 d->systemClip = region;
931 // Be backward compatible and only call d->systemStateChanged()
932 // if we currently have a system transform/viewport set.
933 if (d->hasSystemTransform || d->hasSystemViewport) {
934 d->transformSystemClip();
935 d->systemStateChanged();
942 Returns the system clip. The system clip is read only while the
943 painter is active. An empty region indicates that system clip
947 QRegion QPaintEngine::systemClip() const
949 return d_func()->systemClip;
955 Sets the target rect for drawing within the backing store. This
956 function should ONLY be used by the backing store.
958 void QPaintEngine::setSystemRect(const QRect &rect)
961 qWarning("QPaintEngine::setSystemRect: Should not be changed while engine is active");
964 d_func()->systemRect = rect;
970 Retrieves the rect for drawing within the backing store. This
971 function should ONLY be used by the backing store.
973 QRect QPaintEngine::systemRect() const
975 return d_func()->systemRect;
978 void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt &ti)
980 if (!ti.glyphs.numGlyphs)
983 // any fixes here should probably also be done in QFontEngineBox::draw
984 const int size = qRound(ti.fontEngine->ascent());
985 QVarLengthArray<QFixedPoint> positions;
986 QVarLengthArray<glyph_t> glyphs;
987 QTransform matrix = QTransform::fromTranslate(p.x(), p.y() - size);
988 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
989 if (glyphs.size() == 0)
992 QSize s(size - 3, size - 3);
994 QPainter *painter = q_func()->state->painter();
996 painter->setBrush(Qt::NoBrush);
997 QPen pen = painter->pen();
998 pen.setWidthF(ti.fontEngine->lineThickness().toReal());
999 painter->setPen(pen);
1000 for (int k = 0; k < positions.size(); k++)
1001 painter->drawRect(QRectF(positions[k].toPointF(), s));