1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** 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"
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>
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 : QGuiApplication::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 QOpenGLWidget) 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.
417 \sa end(), isActive()
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);
755 path.setFillRule(Qt::WindingFill);
756 if (ti.glyphs.numGlyphs)
757 ti.fontEngine->addOutlineToPath(0, 0, ti.glyphs, &path, ti.flags);
758 if (!path.isEmpty()) {
760 painter()->setRenderHint(QPainter::Antialiasing,
761 bool((painter()->renderHints() & QPainter::TextAntialiasing)
762 && !(painter()->font().styleStrategy() & QFont::NoAntialias)));
763 painter()->translate(p.x(), p.y());
764 painter()->fillPath(path, state->pen().brush());
765 painter()->restore();
770 The default implementation splits the list of lines in \a lines
771 into \a lineCount separate calls to drawPath() or drawPolygon()
772 depending on the feature set of the paint engine.
774 void QPaintEngine::drawLines(const QLineF *lines, int lineCount)
776 for (int i=0; i<lineCount; ++i) {
777 QPointF pts[2] = { lines[i].p1(), lines[i].p2() };
779 if (pts[0] == pts[1]) {
780 if (state->pen().capStyle() != Qt::FlatCap)
785 drawPolygon(pts, 2, PolylineMode);
792 The default implementation converts the first \a lineCount lines
793 in \a lines to a QLineF and calls the floating point version of
796 void QPaintEngine::drawLines(const QLine *lines, int lineCount)
806 Q_ASSERT(sizeof(PointF) == sizeof(QPointF));
807 Q_ASSERT(sizeof(LineF) == sizeof(QLineF));
811 while (i < lineCount && i < 256) {
812 fl[i].p1.x = lines[i].x1();
813 fl[i].p1.y = lines[i].y1();
814 fl[i].p2.x = lines[i].x2();
815 fl[i].p2.y = lines[i].y2();
818 drawLines((QLineF *)(void *)fl, i);
828 The default implementation converts the first \a rectCount
829 rectangles in the buffer \a rects to a QRectF and calls the
830 floating point version of this function.
832 void QPaintEngine::drawRects(const QRect *rects, int rectCount)
840 Q_ASSERT(sizeof(RectF) == sizeof(QRectF));
844 while (i < rectCount && i < 256) {
845 fr[i].x = rects[i].x();
846 fr[i].y = rects[i].y();
847 fr[i].w = rects[i].width();
848 fr[i].h = rects[i].height();
851 drawRects((QRectF *)(void *)fr, i);
858 Draws the first \a rectCount rectangles in the buffer \a
859 rects. The default implementation of this function calls drawPath()
860 or drawPolygon() depending on the feature set of the paint engine.
862 void QPaintEngine::drawRects(const QRectF *rects, int rectCount)
864 if (hasFeature(PainterPaths) &&
865 !state->penNeedsResolving() &&
866 !state->brushNeedsResolving()) {
867 for (int i=0; i<rectCount; ++i) {
869 path.addRect(rects[i]);
875 for (int i=0; i<rectCount; ++i) {
876 QRectF rf = rects[i];
877 QPointF pts[4] = { QPointF(rf.x(), rf.y()),
878 QPointF(rf.x() + rf.width(), rf.y()),
879 QPointF(rf.x() + rf.width(), rf.y() + rf.height()),
880 QPointF(rf.x(), rf.y() + rf.height()) };
881 drawPolygon(pts, 4, ConvexMode);
888 Sets the paintdevice that this engine operates on to \a device
890 void QPaintEngine::setPaintDevice(QPaintDevice *device)
892 d_func()->pdev = device;
896 Returns the device that this engine is painting on, if painting is
897 active; otherwise returns 0.
899 QPaintDevice *QPaintEngine::paintDevice() const
901 return d_func()->pdev;
908 Returns the offset from the painters origo to the engines
909 origo. This value is used by QPainter for engines who have
910 internal double buffering.
912 This function only makes sense when the engine is active.
914 QPoint QPaintEngine::coordinateOffset() const
922 Sets the system clip for this engine. The system clip defines the
923 basis area that the engine has to draw in. All clips that are
924 set will be be an intersection with the system clip.
926 Reset the systemclip to no clip by setting an empty region.
928 void QPaintEngine::setSystemClip(const QRegion ®ion)
931 d->systemClip = region;
932 // Be backward compatible and only call d->systemStateChanged()
933 // if we currently have a system transform/viewport set.
934 if (d->hasSystemTransform || d->hasSystemViewport) {
935 d->transformSystemClip();
936 d->systemStateChanged();
943 Returns the system clip. The system clip is read only while the
944 painter is active. An empty region indicates that system clip
948 QRegion QPaintEngine::systemClip() const
950 return d_func()->systemClip;
956 Sets the target rect for drawing within the backing store. This
957 function should ONLY be used by the backing store.
959 void QPaintEngine::setSystemRect(const QRect &rect)
962 qWarning("QPaintEngine::setSystemRect: Should not be changed while engine is active");
965 d_func()->systemRect = rect;
971 Retrieves the rect for drawing within the backing store. This
972 function should ONLY be used by the backing store.
974 QRect QPaintEngine::systemRect() const
976 return d_func()->systemRect;
979 void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt &ti)
981 if (!ti.glyphs.numGlyphs)
984 // any fixes here should probably also be done in QFontEngineBox::draw
985 const int size = qRound(ti.fontEngine->ascent());
986 QVarLengthArray<QFixedPoint> positions;
987 QVarLengthArray<glyph_t> glyphs;
988 QTransform matrix = QTransform::fromTranslate(p.x(), p.y() - size);
989 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
990 if (glyphs.size() == 0)
993 QSize s(size - 3, size - 3);
995 QPainter *painter = q_func()->state->painter();
997 painter->setBrush(Qt::NoBrush);
998 QPen pen = painter->pen();
999 pen.setWidthF(ti.fontEngine->lineThickness().toReal());
1000 painter->setPen(pen);
1001 for (int k = 0; k < positions.size(); k++)
1002 painter->drawRect(QRectF(positions[k].toPointF(), s));