1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39#include "qpaintengine.h"
40#include "qpaintengine_p.h"
41#include "qpainter_p.h"
42#include "qpolygon.h"
43#include "qbitmap.h"
44#include <qdebug.h>
45#include <qmath.h>
46#include <qguiapplication.h>
47#include <qvarlengtharray.h>
48#include <qpa/qplatformintegration.h>
49#include <qpa/qplatformpixmap.h>
50#include <private/qfontengine_p.h>
51#include <private/qguiapplication_p.h>
52#include <private/qpaintengineex_p.h>
53#include <private/qtextengine_p.h>
54
55
56QT_BEGIN_NAMESPACE
57
58/*!
59 \class QTextItem
60 \inmodule QtGui
61
62 \brief The QTextItem class provides all the information required to draw
63 text in a custom paint engine.
64
65 When you reimplement your own paint engine, you must reimplement
66 QPaintEngine::drawTextItem(), a function that takes a QTextItem as
67 one of its arguments.
68*/
69
70/*!
71 \enum QTextItem::RenderFlag
72
73 \value RightToLeft Render the text from right to left.
74 \value Overline Paint a line above the text.
75 \value Underline Paint a line under the text.
76 \value StrikeOut Paint a line through the text.
77 \omitvalue Dummy
78*/
79
80
81/*!
82 \fn qreal QTextItem::descent() const
83
84 Corresponds to the \l{QFontMetrics::descent()}{descent} of the piece of text that is drawn.
85*/
86qreal QTextItem::descent() const
87{
88 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
89 return ti->descent.toReal();
90}
91
92/*!
93 \fn qreal QTextItem::ascent() const
94
95 Corresponds to the \l{QFontMetrics::ascent()}{ascent} of the piece of text that is drawn.
96*/
97qreal QTextItem::ascent() const
98{
99 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
100 return ti->ascent.toReal();
101}
102
103/*!
104 \fn qreal QTextItem::width() const
105
106 Specifies the total width of the text to be drawn.
107*/
108qreal QTextItem::width() const
109{
110 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
111 return ti->width.toReal();
112}
113
114/*!
115 \fn QTextItem::RenderFlags QTextItem::renderFlags() const
116
117 Returns the render flags used.
118*/
119QTextItem::RenderFlags QTextItem::renderFlags() const
120{
121 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
122 return ti->flags;
123}
124
125/*!
126 \fn QString QTextItem::text() const
127
128 Returns the text that should be drawn.
129*/
130QString QTextItem::text() const
131{
132 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
133 return QString(ti->chars, ti->num_chars);
134}
135
136/*!
137 \fn QFont QTextItem::font() const
138
139 Returns the font that should be used to draw the text.
140*/
141QFont QTextItem::font() const
142{
143 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
144 return ti->f ? *ti->f : QGuiApplication::font();
145}
146
147
148/*!
149 \class QPaintEngine
150 \ingroup painting
151 \inmodule QtGui
152
153 \brief The QPaintEngine class provides an abstract definition of how
154 QPainter draws to a given device on a given platform.
155
156 Qt provides several premade implementations of QPaintEngine for the
157 different painter backends we support. The primary paint engine
158 provided is the raster paint engine, which contains a software
159 rasterizer which supports the full feature set on all supported platforms.
160 This is the default for painting on QWidget-based classes in e.g. on Windows,
161 X11 and \macos, it is the backend for painting on QImage and it is
162 used as a fallback for paint engines that do not support a certain
163 capability. In addition we provide QPaintEngine implementations for
164 OpenGL (accessible through QOpenGLWidget) and printing (which allows using
165 QPainter to draw on a QPrinter object).
166
167 If one wants to use QPainter to draw to a different backend,
168 one must subclass QPaintEngine and reimplement all its virtual
169 functions. The QPaintEngine implementation is then made available by
170 subclassing QPaintDevice and reimplementing the virtual function
171 QPaintDevice::paintEngine().
172
173 QPaintEngine is created and owned by the QPaintDevice that created it.
174
175 \sa QPainter, QPaintDevice::paintEngine(), {Paint System}
176*/
177
178/*!
179 \enum QPaintEngine::PaintEngineFeature
180
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.
186
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
194 width 2).
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
210 paint events.
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
214 patterns.
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
221 drawing primitives.
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
225 used as a bit mask.
226*/
227
228/*!
229 \enum QPaintEngine::PolygonDrawMode
230
231 \value OddEvenMode The polygon should be drawn using OddEven fill
232 rule.
233
234 \value WindingMode The polygon should be drawn using Winding fill rule.
235
236 \value ConvexMode The polygon is a convex polygon and can be drawn
237 using specialized algorithms where available.
238
239 \value PolylineMode Only the outline of the polygon should be
240 drawn.
241
242*/
243
244/*!
245 \enum QPaintEngine::DirtyFlag
246
247 \value DirtyPen The pen is dirty and needs to be updated.
248
249 \value DirtyBrush The brush is dirty and needs to be updated.
250
251 \value DirtyBrushOrigin The brush origin is dirty and needs to
252 updated.
253
254 \value DirtyFont The font is dirty and needs to be updated.
255
256 \value DirtyBackground The background is dirty and needs to be
257 updated.
258
259 \value DirtyBackgroundMode The background mode is dirty and needs
260 to be updated.
261
262 \value DirtyTransform The transform is dirty and needs to be
263 updated.
264
265 \value DirtyClipRegion The clip region is dirty and needs to be
266 updated.
267
268 \value DirtyClipPath The clip path is dirty and needs to be
269 updated.
270
271 \value DirtyHints The render hints is dirty and needs to be
272 updated.
273
274 \value DirtyCompositionMode The composition mode is dirty and
275 needs to be updated.
276
277 \value DirtyClipEnabled Whether clipping is enabled or not is
278 dirty and needs to be updated.
279
280 \value DirtyOpacity The constant opacity has changed and needs to
281 be updated as part of the state change in
282 QPaintEngine::updateState().
283
284 \value AllDirty Convenience enum used internally.
285
286 These types are used by QPainter to trigger lazy updates of the
287 various states in the QPaintEngine using
288 QPaintEngine::updateState().
289
290 A paint engine must update every dirty state.
291*/
292
293/*!
294 \fn void QPaintEngine::syncState()
295
296 \internal
297
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.
301*/
302void QPaintEngine::syncState()
303{
304 Q_ASSERT(state);
305 updateState(*state);
306
307 if (isExtended())
308 static_cast<QPaintEngineEx *>(this)->sync();
309}
310
311static QPaintEngine *qt_polygon_recursion = nullptr;
312struct QT_Point {
313 int x;
314 int y;
315};
316Q_DECLARE_TYPEINFO(QT_Point, Q_PRIMITIVE_TYPE);
317
318/*!
319 \fn void QPaintEngine::drawPolygon(const QPointF *points, int pointCount,
320 PolygonDrawMode mode)
321
322 Reimplement this virtual function to draw the polygon defined
323 by the \a pointCount first points in \a points, using mode \a
324 mode.
325
326 \note At least one of the drawPolygon() functions must be reimplemented.
327*/
328void QPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
329{
330 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
331 "At least one drawPolygon function must be implemented");
332 qt_polygon_recursion = this;
333 Q_ASSERT(sizeof(QT_Point) == sizeof(QPoint));
334 QVarLengthArray<QT_Point> p(pointCount);
335 for (int i = 0; i < pointCount; ++i) {
336 p[i].x = qRound(points[i].x());
337 p[i].y = qRound(points[i].y());
338 }
339 drawPolygon((QPoint *)p.data(), pointCount, mode);
340 qt_polygon_recursion = nullptr;
341}
342
343struct QT_PointF {
344 qreal x;
345 qreal y;
346};
347Q_DECLARE_TYPEINFO(QT_PointF, Q_PRIMITIVE_TYPE);
348
349/*!
350 \overload
351
352 Reimplement this virtual function to draw the polygon defined by the
353 \a pointCount first points in \a points, using mode \a mode.
354
355 \note At least one of the drawPolygon() functions must be reimplemented.
356*/
357void QPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
358{
359 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
360 "At least one drawPolygon function must be implemented");
361 qt_polygon_recursion = this;
362 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
363 QVarLengthArray<QT_PointF> p(pointCount);
364 for (int i=0; i<pointCount; ++i) {
365 p[i].x = points[i].x();
366 p[i].y = points[i].y();
367 }
368 drawPolygon((QPointF *)p.data(), pointCount, mode);
369 qt_polygon_recursion = nullptr;
370}
371
372/*!
373 \enum QPaintEngine::Type
374
375 \value X11
376 \value Windows
377 \value MacPrinter
378 \value CoreGraphics \macos's Quartz2D (CoreGraphics)
379 \value QuickDraw \macos's QuickDraw
380 \value QWindowSystem Qt for Embedded Linux
381 \value OpenGL
382 \value Picture QPicture format
383 \value SVG Scalable Vector Graphics XML format
384 \value Raster
385 \value Direct3D Windows only, Direct3D based engine
386 \value Pdf Portable Document Format
387 \value OpenVG
388 \value User First user type ID
389 \value MaxUser Last user type ID
390 \value OpenGL2
391 \value PaintBuffer
392 \value Blitter
393 \value Direct2D Windows only, Direct2D based engine
394*/
395
396/*!
397 \fn bool QPaintEngine::isActive() const
398
399 Returns \c true if the paint engine is actively drawing; otherwise
400 returns \c false.
401
402 \sa setActive()
403*/
404
405/*!
406 \fn void QPaintEngine::setActive(bool state)
407
408 Sets the active state of the paint engine to \a state.
409
410 \sa isActive()
411*/
412
413/*!
414 \fn bool QPaintEngine::begin(QPaintDevice *pdev)
415
416 Reimplement this function to initialise your paint engine when
417 painting is to start on the paint device \a pdev. Return true if
418 the initialization was successful; otherwise return false.
419
420 \sa end(), isActive()
421*/
422
423/*!
424 \fn bool QPaintEngine::end()
425
426 Reimplement this function to finish painting on the current paint
427 device. Return true if painting was finished successfully;
428 otherwise return false.
429
430 \sa begin(), isActive()
431*/
432
433
434/*!
435 Draws the first \a pointCount points in the buffer \a points
436*/
437void QPaintEngine::drawPoints(const QPointF *points, int pointCount)
438{
439 QPainter *p = painter();
440 if (!p)
441 return;
442
443 qreal penWidth = p->pen().widthF();
444 if (penWidth == 0)
445 penWidth = 1;
446
447 bool ellipses = p->pen().capStyle() == Qt::RoundCap;
448
449 p->save();
450
451 QTransform transform;
452 if (qt_pen_is_cosmetic(p->pen(), p->renderHints())) {
453 transform = p->transform();
454 p->setTransform(QTransform());
455 }
456
457 p->setBrush(p->pen().brush());
458 p->setPen(Qt::NoPen);
459
460 for (int i=0; i<pointCount; ++i) {
461 QPointF pos = transform.map(points[i]);
462 QRectF rect(pos.x() - penWidth / 2, pos.y() - penWidth / 2, penWidth, penWidth);
463
464 if (ellipses)
465 p->drawEllipse(rect);
466 else
467 p->drawRect(rect);
468 }
469
470 p->restore();
471}
472
473
474/*!
475 Draws the first \a pointCount points in the buffer \a points
476
477 The default implementation converts the first \a pointCount QPoints in \a points
478 to QPointFs and calls the floating point version of drawPoints.
479
480*/
481void QPaintEngine::drawPoints(const QPoint *points, int pointCount)
482{
483 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
484 QT_PointF fp[256];
485 while (pointCount) {
486 int i = 0;
487 while (i < pointCount && i < 256) {
488 fp[i].x = points[i].x();
489 fp[i].y = points[i].y();
490 ++i;
491 }
492 drawPoints((QPointF *)(void *)fp, i);
493 points += i;
494 pointCount -= i;
495 }
496}
497
498/*!
499 \fn void QPaintEngine::drawEllipse(const QRectF &rect)
500
501 Reimplement this function to draw the largest ellipse that can be
502 contained within rectangle \a rect.
503
504 The default implementation calls drawPolygon().
505*/
506void QPaintEngine::drawEllipse(const QRectF &rect)
507{
508 QPainterPath path;
509 path.addEllipse(rect);
510 if (hasFeature(PainterPaths)) {
511 drawPath(path);
512 } else {
513 QPolygonF polygon = path.toFillPolygon();
514 drawPolygon(polygon.data(), polygon.size(), ConvexMode);
515 }
516}
517
518/*!
519 The default implementation of this function calls the floating
520 point version of this function
521*/
522void QPaintEngine::drawEllipse(const QRect &rect)
523{
524 drawEllipse(QRectF(rect));
525}
526
527/*!
528 \fn void QPaintEngine::drawPixmap(const QRectF &r, const QPixmap
529 &pm, const QRectF &sr)
530
531 Reimplement this function to draw the part of the \a pm
532 specified by the \a sr rectangle in the given \a r.
533*/
534
535
536void qt_fill_tile(QPixmap *tile, const QPixmap &pixmap)
537{
538 QPainter p(tile);
539 p.drawPixmap(0, 0, pixmap);
540 int x = pixmap.width();
541 while (x < tile->width()) {
542 p.drawPixmap(x, 0, *tile, 0, 0, x, pixmap.height());
543 x *= 2;
544 }
545 int y = pixmap.height();
546 while (y < tile->height()) {
547 p.drawPixmap(0, y, *tile, 0, 0, tile->width(), y);
548 y *= 2;
549 }
550}
551
552Q_GUI_EXPORT void qt_draw_tile(QPaintEngine *gc, qreal x, qreal y, qreal w, qreal h,
553 const QPixmap &pixmap, qreal xOffset, qreal yOffset)
554{
555 qreal yPos, xPos, drawH, drawW, yOff, xOff;
556 yPos = y;
557 yOff = yOffset;
558 while(yPos < y + h) {
559 drawH = pixmap.height() - yOff; // Cropping first row
560 if (yPos + drawH > y + h) // Cropping last row
561 drawH = y + h - yPos;
562 xPos = x;
563 xOff = xOffset;
564 while(xPos < x + w) {
565 drawW = pixmap.width() - xOff; // Cropping first column
566 if (xPos + drawW > x + w) // Cropping last column
567 drawW = x + w - xPos;
568 if (drawW > 0 && drawH > 0)
569 gc->drawPixmap(QRectF(xPos, yPos, drawW, drawH), pixmap, QRectF(xOff, yOff, drawW, drawH));
570 xPos += drawW;
571 xOff = 0;
572 }
573 yPos += drawH;
574 yOff = 0;
575 }
576}
577
578
579/*!
580 Reimplement this function to draw the \a pixmap in the given \a
581 rect, starting at the given \a p. The pixmap will be
582 drawn repeatedly until the \a rect is filled.
583*/
584void QPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p)
585{
586 int sw = pixmap.width();
587 int sh = pixmap.height();
588
589 if (sw*sh < 8192 && sw*sh < 16*rect.width()*rect.height()) {
590 int tw = sw, th = sh;
591 while (tw*th < 32678 && tw < rect.width()/2)
592 tw *= 2;
593 while (tw*th < 32678 && th < rect.height()/2)
594 th *= 2;
595 QPixmap tile;
596 if (pixmap.depth() == 1) {
597 tile = QBitmap(tw, th);
598 } else {
599 tile = QPixmap(tw, th);
600 if (pixmap.hasAlphaChannel())
601 tile.fill(Qt::transparent);
602 }
603 qt_fill_tile(&tile, pixmap);
604 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), tile, p.x(), p.y());
605 } else {
606 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), pixmap, p.x(), p.y());
607 }
608}
609
610/*!
611 \fn void QPaintEngine::drawImage(const QRectF &rectangle, const QImage
612 &image, const QRectF &sr, Qt::ImageConversionFlags flags)
613
614 Reimplement this function to draw the part of the \a image
615 specified by the \a sr rectangle in the given \a rectangle using
616 the given conversion flags \a flags, to convert it to a pixmap.
617*/
618
619void QPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
620 Qt::ImageConversionFlags flags)
621{
622 QRectF baseSize(0, 0, image.width(), image.height());
623 QImage im = image;
624 if (baseSize != sr)
625 im = im.copy(qFloor(sr.x()), qFloor(sr.y()),
626 qCeil(sr.width()), qCeil(sr.height()));
627 QPixmap pm = QPixmap::fromImage(im, flags);
628 drawPixmap(r, pm, QRectF(QPointF(0, 0), pm.size()));
629}
630
631/*!
632 \fn Type QPaintEngine::type() const
633
634 Reimplement this function to return the paint engine \l{Type}.
635*/
636
637/*!
638 \fn void QPaintEngine::fix_neg_rect(int *x, int *y, int *w, int *h);
639
640 \internal
641*/
642
643/*!
644 \fn bool QPaintEngine::testDirty(DirtyFlags df)
645
646 \internal
647*/
648
649/*!
650 \fn void QPaintEngine::clearDirty(DirtyFlags df)
651
652 \internal
653*/
654
655/*!
656 \fn void QPaintEngine::setDirty(DirtyFlags df)
657
658 \internal
659*/
660
661/*!
662 \fn bool QPaintEngine::hasFeature(PaintEngineFeatures feature) const
663
664 Returns \c true if the paint engine supports the specified \a
665 feature; otherwise returns \c false.
666*/
667
668/*!
669 \fn bool QPaintEngine::isExtended() const
670
671 \internal
672
673 Returns \c true if the paint engine is a QPaintEngineEx derivative.
674*/
675
676/*!
677 \fn void QPaintEngine::updateState(const QPaintEngineState &state)
678
679 Reimplement this function to update the state of a paint engine.
680
681 When implemented, this function is responsible for checking the
682 paint engine's current \a state and update the properties that are
683 changed. Use the QPaintEngineState::state() function to find out
684 which properties that must be updated, then use the corresponding
685 \l {GetFunction}{get function} to retrieve the current values for
686 the given properties.
687
688 \sa QPaintEngineState
689*/
690
691/*!
692 Creates a paint engine with the featureset specified by \a caps.
693*/
694
695QPaintEngine::QPaintEngine(PaintEngineFeatures caps)
696 : state(nullptr),
697 gccaps(caps),
698 active(0),
699 selfDestruct(false),
700 extended(false),
701 d_ptr(new QPaintEnginePrivate)
702{
703 d_ptr->q_ptr = this;
704}
705
706/*!
707 \internal
708*/
709
710QPaintEngine::QPaintEngine(QPaintEnginePrivate &dptr, PaintEngineFeatures caps)
711 : state(nullptr),
712 gccaps(caps),
713 active(0),
714 selfDestruct(false),
715 extended(false),
716 d_ptr(&dptr)
717{
718 d_ptr->q_ptr = this;
719}
720
721/*!
722 Destroys the paint engine.
723*/
724QPaintEngine::~QPaintEngine()
725{
726}
727
728/*!
729 Returns the paint engine's painter.
730*/
731QPainter *QPaintEngine::painter() const
732{
733 return state ? state->painter() : nullptr;
734}
735
736/*!
737 The default implementation ignores the \a path and does nothing.
738*/
739
740void QPaintEngine::drawPath(const QPainterPath &)
741{
742 if (hasFeature(PainterPaths)) {
743 qWarning("QPaintEngine::drawPath: Must be implemented when feature PainterPaths is set");
744 }
745}
746
747/*!
748 This function draws the text item \a textItem at position \a p. The
749 default implementation of this function converts the text to a
750 QPainterPath and paints the resulting path.
751*/
752
753void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
754{
755 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
756 if (ti.glyphs.numGlyphs == 0)
757 return;
758
759 if (ti.fontEngine->glyphFormat == QFontEngine::Format_ARGB) {
760 QVarLengthArray<QFixedPoint> positions;
761 QVarLengthArray<glyph_t> glyphs;
762 QTransform matrix = QTransform::fromTranslate(p.x(), p.y() - ti.fontEngine->ascent().toReal());
763 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
764 painter()->save();
765 painter()->setRenderHint(QPainter::SmoothPixmapTransform,
766 bool((painter()->renderHints() & QPainter::TextAntialiasing)
767 && !(painter()->font().styleStrategy() & QFont::NoAntialias)));
768 for (int i = 0; i < ti.glyphs.numGlyphs; ++i) {
769 QImage glyph = ti.fontEngine->bitmapForGlyph(glyphs[i], QFixed(), QTransform());
770 painter()->drawImage(positions[i].x.toReal(), positions[i].y.toReal(), glyph);
771 }
772 painter()->restore();
773 return;
774 }
775
776 QPainterPath path;
777 path.setFillRule(Qt::WindingFill);
778 ti.fontEngine->addOutlineToPath(0, 0, ti.glyphs, &path, ti.flags);
779 if (!path.isEmpty()) {
780 painter()->save();
781 painter()->setRenderHint(QPainter::Antialiasing,
782 bool((painter()->renderHints() & QPainter::TextAntialiasing)
783 && !(painter()->font().styleStrategy() & QFont::NoAntialias)));
784 painter()->translate(p.x(), p.y());
785 painter()->fillPath(path, painter()->pen().brush());
786 painter()->restore();
787 }
788}
789
790/*!
791 The default implementation splits the list of lines in \a lines
792 into \a lineCount separate calls to drawPath() or drawPolygon()
793 depending on the feature set of the paint engine.
794*/
795void QPaintEngine::drawLines(const QLineF *lines, int lineCount)
796{
797 for (int i=0; i<lineCount; ++i) {
798 QPointF pts[2] = { lines[i].p1(), lines[i].p2() };
799
800 if (pts[0] == pts[1]) {
801 if (state->pen().capStyle() != Qt::FlatCap)
802 drawPoints(pts, 1);
803 continue;
804 }
805
806 drawPolygon(pts, 2, PolylineMode);
807 }
808}
809
810/*!
811 \overload
812
813 The default implementation converts the first \a lineCount lines
814 in \a lines to a QLineF and calls the floating point version of
815 this function.
816*/
817void QPaintEngine::drawLines(const QLine *lines, int lineCount)
818{
819 struct PointF {
820 qreal x;
821 qreal y;
822 };
823 struct LineF {
824 PointF p1;
825 PointF p2;
826 };
827 Q_ASSERT(sizeof(PointF) == sizeof(QPointF));
828 Q_ASSERT(sizeof(LineF) == sizeof(QLineF));
829 LineF fl[256];
830 while (lineCount) {
831 int i = 0;
832 while (i < lineCount && i < 256) {
833 fl[i].p1.x = lines[i].x1();
834 fl[i].p1.y = lines[i].y1();
835 fl[i].p2.x = lines[i].x2();
836 fl[i].p2.y = lines[i].y2();
837 ++i;
838 }
839 drawLines((QLineF *)(void *)fl, i);
840 lines += i;
841 lineCount -= i;
842 }
843}
844
845
846/*!
847 \overload
848
849 The default implementation converts the first \a rectCount
850 rectangles in the buffer \a rects to a QRectF and calls the
851 floating point version of this function.
852*/
853void QPaintEngine::drawRects(const QRect *rects, int rectCount)
854{
855 struct RectF {
856 qreal x;
857 qreal y;
858 qreal w;
859 qreal h;
860 };
861 Q_ASSERT(sizeof(RectF) == sizeof(QRectF));
862 RectF fr[256];
863 while (rectCount) {
864 int i = 0;
865 while (i < rectCount && i < 256) {
866 fr[i].x = rects[i].x();
867 fr[i].y = rects[i].y();
868 fr[i].w = rects[i].width();
869 fr[i].h = rects[i].height();
870 ++i;
871 }
872 drawRects((QRectF *)(void *)fr, i);
873 rects += i;
874 rectCount -= i;
875 }
876}
877
878/*!
879 Draws the first \a rectCount rectangles in the buffer \a
880 rects. The default implementation of this function calls drawPath()
881 or drawPolygon() depending on the feature set of the paint engine.
882*/
883void QPaintEngine::drawRects(const QRectF *rects, int rectCount)
884{
885 if (hasFeature(PainterPaths) &&
886 !state->penNeedsResolving() &&
887 !state->brushNeedsResolving()) {
888 for (int i=0; i<rectCount; ++i) {
889 QPainterPath path;
890 path.addRect(rects[i]);
891 if (path.isEmpty())
892 continue;
893 drawPath(path);
894 }
895 } else {
896 for (int i=0; i<rectCount; ++i) {
897 QRectF rf = rects[i];
898 QPointF pts[4] = { QPointF(rf.x(), rf.y()),
899 QPointF(rf.x() + rf.width(), rf.y()),
900 QPointF(rf.x() + rf.width(), rf.y() + rf.height()),
901 QPointF(rf.x(), rf.y() + rf.height()) };
902 drawPolygon(pts, 4, ConvexMode);
903 }
904 }
905}
906
907/*!
908 \internal
909 Sets the paintdevice that this engine operates on to \a device
910*/
911void QPaintEngine::setPaintDevice(QPaintDevice *device)
912{
913 d_func()->pdev = device;
914}
915
916/*!
917 Returns the device that this engine is painting on, if painting is
918 active; otherwise returns \nullptr.
919*/
920QPaintDevice *QPaintEngine::paintDevice() const
921{
922 return d_func()->pdev;
923}
924
925
926/*!
927 \internal
928
929 Returns the offset from the painters origo to the engines
930 origo. This value is used by QPainter for engines who have
931 internal double buffering.
932
933 This function only makes sense when the engine is active.
934*/
935QPoint QPaintEngine::coordinateOffset() const
936{
937 return QPoint();
938}
939
940/*!
941 \internal
942
943 Sets the system clip for this engine. The system clip defines the
944 basis area that the engine has to draw in. All clips that are
945 set will be an intersection with the system clip.
946
947 Reset the systemclip to no clip by setting an empty region.
948*/
949void QPaintEngine::setSystemClip(const QRegion &region)
950{
951 Q_D(QPaintEngine);
952 d->baseSystemClip = region;
953 // Be backward compatible and only call d->systemStateChanged()
954 // if we currently have a system transform/viewport set.
955 d->updateSystemClip();
956 if (d->hasSystemTransform || d->hasSystemViewport) {
957 d->systemStateChanged();
958 }
959}
960
961/*!
962 \internal
963
964 Returns the system clip. The system clip is read only while the
965 painter is active. An empty region indicates that system clip
966 is not in use.
967*/
968
969QRegion QPaintEngine::systemClip() const
970{
971 return d_func()->systemClip;
972}
973
974/*!
975 \internal
976
977 Sets the target rect for drawing within the backing store. This
978 function should ONLY be used by the backing store.
979*/
980void QPaintEngine::setSystemRect(const QRect &rect)
981{
982 if (isActive()) {
983 qWarning("QPaintEngine::setSystemRect: Should not be changed while engine is active");
984 return;
985 }
986 d_func()->systemRect = rect;
987}
988
989/*!
990 \internal
991
992 Retrieves the rect for drawing within the backing store. This
993 function should ONLY be used by the backing store.
994 */
995QRect QPaintEngine::systemRect() const
996{
997 return d_func()->systemRect;
998}
999
1000/*!
1001 \internal
1002
1003 Creates a QPixmap optimized for this paint engine and device.
1004*/
1005QPixmap QPaintEngine::createPixmap(QSize size)
1006{
1007 if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
1008 qWarning("QPaintEngine::createPixmap: QPixmap cannot be created without a QGuiApplication");
1009 return QPixmap();
1010 }
1011
1012 QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
1013 data->resize(size.width(), size.height());
1014 return QPixmap(data.take());
1015}
1016
1017/*!
1018 \internal
1019
1020 Creates a QPixmap optimized for this paint engine and device.
1021*/
1022QPixmap QPaintEngine::createPixmapFromImage(QImage image, Qt::ImageConversionFlags flags)
1023{
1024 if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
1025 qWarning("QPaintEngine::createPixmapFromImage: QPixmap cannot be created without a QGuiApplication");
1026 return QPixmap();
1027 }
1028
1029 QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
1030 if (image.isDetached())
1031 data->fromImageInPlace(image, flags);
1032 else
1033 data->fromImage(image, flags);
1034 return QPixmap(data.take());
1035}
1036
1037QPaintEnginePrivate::~QPaintEnginePrivate()
1038{
1039}
1040
1041void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt &ti)
1042{
1043 if (!ti.glyphs.numGlyphs)
1044 return;
1045
1046 // any fixes here should probably also be done in QFontEngineBox::draw
1047 const int size = qRound(ti.fontEngine->ascent());
1048 QVarLengthArray<QFixedPoint> positions;
1049 QVarLengthArray<glyph_t> glyphs;
1050 QTransform matrix = QTransform::fromTranslate(p.x(), p.y() - size);
1051 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
1052 if (glyphs.size() == 0)
1053 return;
1054
1055 QSize s(size - 3, size - 3);
1056
1057 QPainter *painter = q_func()->state->painter();
1058 painter->save();
1059 painter->setBrush(Qt::NoBrush);
1060 QPen pen = painter->pen();
1061 pen.setWidthF(ti.fontEngine->lineThickness().toReal());
1062 painter->setPen(pen);
1063 for (int k = 0; k < positions.size(); k++)
1064 painter->drawRect(QRectF(positions[k].toPointF(), s));
1065 painter->restore();
1066}
1067
1068QT_END_NAMESPACE
1069