painting/qpainter.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/****************************************************************************-
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/****************************************************************************
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
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 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. -
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 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. -
24** -
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. -
28** -
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. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42// QtCore -
43#include <qdebug.h> -
44#include <qmath.h> -
45#include <qmutex.h> -
46 -
47// QtGui -
48#include "qbitmap.h" -
49#include "qimage.h" -
50#include "qpaintdevice.h" -
51#include "qpaintengine.h" -
52#include "qpainter.h" -
53#include "qpainter_p.h" -
54#include "qpainterpath.h" -
55#include "qpicture.h" -
56#include "qpixmapcache.h" -
57#include "qpolygon.h" -
58#include "qtextlayout.h" -
59#include "qthread.h" -
60#include "qvarlengtharray.h" -
61#include "qstatictext.h" -
62#include "qglyphrun.h" -
63 -
64#include <qpa/qplatformtheme.h> -
65 -
66#include <private/qfontengine_p.h> -
67#include <private/qpaintengine_p.h> -
68#include <private/qemulationpaintengine_p.h> -
69#include <private/qpainterpath_p.h> -
70#include <private/qtextengine_p.h> -
71#include <private/qpaintengine_raster_p.h> -
72#include <private/qmath_p.h> -
73#include <private/qstatictext_p.h> -
74#include <private/qglyphrun_p.h> -
75#include <private/qhexstring_p.h> -
76#include <private/qguiapplication_p.h> -
77#include <private/qrawfont_p.h> -
78 -
79QT_BEGIN_NAMESPACE -
80 -
81#define QGradient_StretchToDevice 0x10000000 -
82#define QPaintEngine_OpaqueBackground 0x40000000 -
83 -
84// #define QT_DEBUG_DRAW -
85#ifdef QT_DEBUG_DRAW -
86bool qt_show_painter_debug_output = true; -
87#endif -
88 -
89extern QPixmap qt_pixmapForBrush(int style, bool invert); -
90 -
91void qt_format_text(const QFont &font, -
92 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect, -
93 int tabstops, int* tabarray, int tabarraylen, -
94 QPainter *painter); -
95static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine, -
96 QTextCharFormat::UnderlineStyle underlineStyle, -
97 QTextItem::RenderFlags flags, qreal width, -
98 const QTextCharFormat &charFormat); -
99// Helper function to calculate left most position, width and flags for decoration drawing -
100Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, -
101 const QFixedPoint *positions, int glyphCount, -
102 QFontEngine *fontEngine, const QFont &font, -
103 const QTextCharFormat &charFormat); -
104 -
105static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush) -
106{ -
107 switch (brush.style()) { -
108 case Qt::LinearGradientPattern: -
109 case Qt::RadialGradientPattern: -
110 case Qt::ConicalGradientPattern: -
111 return brush.gradient()->coordinateMode(); -
112 default: -
113 ; -
114 } -
115 return QGradient::LogicalMode; -
116} -
117 -
118/* Returns true if the gradient requires stretch to device...*/ -
119static inline bool check_gradient(const QBrush &brush) -
120{ -
121 return coordinateMode(brush) == QGradient::StretchToDeviceMode; -
122} -
123 -
124extern bool qHasPixmapTexture(const QBrush &); -
125 -
126static inline bool is_brush_transparent(const QBrush &brush) { -
127 Qt::BrushStyle s = brush.style(); -
128 bool brushBitmap = qHasPixmapTexture(brush) -
129 ? brush.texture().isQBitmap() -
130 : (brush.textureImage().depth() == 1); -
131 return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern) -
132 || (s == Qt::TexturePattern && brushBitmap)); -
133} -
134 -
135static inline bool is_pen_transparent(const QPen &pen) { -
136 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush()); -
137} -
138 -
139/* Discards the emulation flags that are not relevant for line drawing -
140 and returns the result -
141*/ -
142static inline uint line_emulation(uint emulation) -
143{ -
144 return emulation & (QPaintEngine::PrimitiveTransform -
145 | QPaintEngine::AlphaBlend -
146 | QPaintEngine::Antialiasing -
147 | QPaintEngine::BrushStroke -
148 | QPaintEngine::ConstantOpacity -
149 | QGradient_StretchToDevice -
150 | QPaintEngine::ObjectBoundingModeGradients -
151 | QPaintEngine_OpaqueBackground); -
152} -
153 -
154#ifndef QT_NO_DEBUG -
155static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false) -
156{ -
157 switch (devType) { -
158 case QInternal::Image: -
159 case QInternal::Printer: -
160 case QInternal::Picture: -
161 // can be drawn onto these devices safely from any thread -
162 if (extraCondition) -
163 break; -
164 default: -
165 if (!extraCondition && QThread::currentThread() != qApp->thread()) { -
166 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what); -
167 return false; -
168 } -
169 break; -
170 } -
171 return true; -
172} -
173#endif -
174 -
175void QPainterPrivate::checkEmulation() -
176{ -
177 Q_ASSERT(extended); -
178 if (extended->flags() & QPaintEngineEx::DoNotEmulate) -
179 return; -
180 -
181 bool doEmulation = false; -
182 if (state->bgMode == Qt::OpaqueMode) -
183 doEmulation = true; -
184 -
185 const QGradient *bg = state->brush.gradient(); -
186 if (bg && bg->coordinateMode() > QGradient::LogicalMode) -
187 doEmulation = true; -
188 -
189 const QGradient *pg = qpen_brush(state->pen).gradient(); -
190 if (pg && pg->coordinateMode() > QGradient::LogicalMode) -
191 doEmulation = true; -
192 -
193 if (doEmulation) { -
194 if (extended != emulationEngine) { -
195 if (!emulationEngine) -
196 emulationEngine = new QEmulationPaintEngine(extended); -
197 extended = emulationEngine; -
198 extended->setState(state); -
199 } -
200 } else if (emulationEngine == extended) { -
201 extended = emulationEngine->real_engine; -
202 } -
203} -
204 -
205 -
206QPainterPrivate::~QPainterPrivate() -
207{ -
208 delete emulationEngine; -
209 for (int i=0; i<states.size(); ++i) -
210 delete states.at(i); -
211 -
212 if (dummyState) -
213 delete dummyState; -
214} -
215 -
216 -
217QTransform QPainterPrivate::viewTransform() const -
218{ -
219 if (state->VxF) { -
220 qreal scaleW = qreal(state->vw)/qreal(state->ww); -
221 qreal scaleH = qreal(state->vh)/qreal(state->wh); -
222 return QTransform(scaleW, 0, 0, scaleH, -
223 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH); -
224 } -
225 return QTransform(); -
226} -
227 -
228QTransform QPainterPrivate::hidpiScaleTransform() const -
229{ -
230#ifdef Q_OS_MAC -
231 // Limited feature introduction for Qt 5.0.0, remove ifdef in a later release. -
232 if (device->devType() == QInternal::Printer || device->physicalDpiX() == 0 || device->logicalDpiX() == 0) -
233 return QTransform(); -
234 const qreal deviceScale = (device->physicalDpiX() / device->logicalDpiX()); -
235 if (deviceScale > 1.0) -
236 return QTransform::fromScale(deviceScale, deviceScale); -
237#endif -
238 return QTransform();
executed: return QTransform();
Execution Count:57707
57707
239} -
240 -
241/* -
242 \internal -
243 Returns true if using a shared painter; otherwise false. -
244*/ -
245bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev) -
246{ -
247 Q_ASSERT(q); -
248 Q_ASSERT(pdev); -
249 -
250 QPainter *sp = pdev->sharedPainter(); -
251 if (!sp) -
252 return false; -
253 -
254 // Save the current state of the shared painter and assign -
255 // the current d_ptr to the shared painter's d_ptr. -
256 sp->save(); -
257 if (!sp->d_ptr->d_ptrs) { -
258 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent -
259 // redirections within the same paintEvent(), which should be enough -
260 // in 99% of all cases). E.g: A renders B which renders C which renders D. -
261 sp->d_ptr->d_ptrs_size = 4; -
262 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *)); -
263 Q_CHECK_PTR(sp->d_ptr->d_ptrs); -
264 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) { -
265 // However, to support corner cases we grow the array dynamically if needed. -
266 sp->d_ptr->d_ptrs_size <<= 1; -
267 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *); -
268 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize)); -
269 } -
270 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data(); -
271 q->d_ptr.take(); -
272 q->d_ptr.reset(sp->d_ptr.data()); -
273 -
274 Q_ASSERT(q->d_ptr->state); -
275 -
276 // Now initialize the painter with correct widget properties. -
277 q->initFrom(pdev); -
278 QPoint offset; -
279 pdev->redirected(&offset); -
280 offset += q->d_ptr->engine->coordinateOffset(); -
281 -
282 // Update system rect. -
283 q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width(); -
284 q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height(); -
285 -
286 // Update matrix. -
287 if (q->d_ptr->state->WxF) { -
288 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix; -
289 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y()); -
290 q->d_ptr->state->worldMatrix = QTransform(); -
291 q->d_ptr->state->WxF = false; -
292 } else { -
293 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y()); -
294 } -
295 q->d_ptr->updateMatrix(); -
296 -
297 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func(); -
298 if (enginePrivate->currentClipDevice == pdev) { -
299 enginePrivate->systemStateChanged(); -
300 return true; -
301 } -
302 -
303 // Update system transform and clip. -
304 enginePrivate->currentClipDevice = pdev; -
305 enginePrivate->setSystemTransform(q->d_ptr->state->matrix); -
306 return true; -
307} -
308 -
309void QPainterPrivate::detachPainterPrivate(QPainter *q) -
310{ -
311 Q_ASSERT(refcount > 1); -
312 Q_ASSERT(q); -
313 -
314 QPainterPrivate *original = d_ptrs[--refcount - 1]; -
315 if (inDestructor) { -
316 inDestructor = false; -
317 if (original) -
318 original->inDestructor = true; -
319 } else if (!original) { -
320 original = new QPainterPrivate(q); -
321 } -
322 -
323 d_ptrs[refcount - 1] = 0; -
324 q->restore(); -
325 q->d_ptr.take(); -
326 q->d_ptr.reset(original); -
327 -
328 if (emulationEngine) { -
329 extended = emulationEngine->real_engine; -
330 delete emulationEngine; -
331 emulationEngine = 0; -
332 } -
333} -
334 -
335 -
336void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op) -
337{ -
338#ifdef QT_DEBUG_DRAW -
339 if (qt_show_painter_debug_output) { -
340 printf("QPainter::drawHelper\n"); -
341 } -
342#endif -
343 -
344 if (originalPath.isEmpty()) -
345 return; -
346 -
347 QPaintEngine::PaintEngineFeatures gradientStretch = -
348 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice -
349 | QPaintEngine::ObjectBoundingModeGradients); -
350 -
351 const bool mustEmulateObjectBoundingModeGradients = extended -
352 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients) -
353 && !engine->hasFeature(QPaintEngine::PatternTransform)); -
354 -
355 if (!(state->emulationSpecifier & ~gradientStretch) -
356 && !mustEmulateObjectBoundingModeGradients) { -
357 drawStretchedGradient(originalPath, op); -
358 return; -
359 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) { -
360 drawOpaqueBackground(originalPath, op); -
361 return; -
362 } -
363 -
364 Q_Q(QPainter); -
365 -
366 qreal strokeOffsetX = 0, strokeOffsetY = 0; -
367 -
368 QPainterPath path = originalPath * state->matrix; -
369 QRectF pathBounds = path.boundingRect(); -
370 QRectF strokeBounds; -
371 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen); -
372 if (doStroke) { -
373 qreal penWidth = state->pen.widthF(); -
374 if (penWidth == 0) { -
375 strokeOffsetX = 1; -
376 strokeOffsetY = 1; -
377 } else { -
378 // In case of complex xform -
379 if (state->matrix.type() > QTransform::TxScale) { -
380 QPainterPathStroker stroker; -
381 stroker.setWidth(penWidth); -
382 stroker.setJoinStyle(state->pen.joinStyle()); -
383 stroker.setCapStyle(state->pen.capStyle()); -
384 QPainterPath stroke = stroker.createStroke(originalPath); -
385 strokeBounds = (stroke * state->matrix).boundingRect(); -
386 } else { -
387 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0); -
388 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0); -
389 } -
390 } -
391 } -
392 -
393 QRect absPathRect; -
394 if (!strokeBounds.isEmpty()) { -
395 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect(); -
396 } else { -
397 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY) -
398 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect(); -
399 } -
400 -
401 if (q->hasClipping()) { -
402 bool hasPerspectiveTransform = false; -
403 for (int i = 0; i < state->clipInfo.size(); ++i) { -
404 const QPainterClipInfo &info = state->clipInfo.at(i); -
405 if (info.matrix.type() == QTransform::TxProject) { -
406 hasPerspectiveTransform = true; -
407 break; -
408 } -
409 } -
410 // avoid mapping QRegions with perspective transforms -
411 if (!hasPerspectiveTransform) { -
412 // The trick with txinv and invMatrix is done in order to -
413 // avoid transforming the clip to logical coordinates, and -
414 // then back to device coordinates. This is a problem with -
415 // QRegion/QRect based clips, since they use integer -
416 // coordinates and converting to/from logical coordinates will -
417 // lose precision. -
418 bool old_txinv = txinv; -
419 QTransform old_invMatrix = invMatrix; -
420 txinv = true; -
421 invMatrix = QTransform(); -
422 QPainterPath clipPath = q->clipPath(); -
423 QRectF r = clipPath.boundingRect().intersected(absPathRect); -
424 absPathRect = r.toAlignedRect(); -
425 txinv = old_txinv; -
426 invMatrix = old_invMatrix; -
427 } -
428 } -
429 -
430// qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d", -
431// devMinX, devMinY, device->width(), device->height()); -
432// qDebug() << " - matrix" << state->matrix; -
433// qDebug() << " - originalPath.bounds" << originalPath.boundingRect(); -
434// qDebug() << " - path.bounds" << path.boundingRect(); -
435 -
436 if (absPathRect.width() <= 0 || absPathRect.height() <= 0) -
437 return; -
438 -
439 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied); -
440 image.fill(0); -
441 -
442 QPainter p(&image); -
443 -
444 p.d_ptr->helper_device = helper_device; -
445 -
446 p.setOpacity(state->opacity); -
447 p.translate(-absPathRect.x(), -absPathRect.y()); -
448 p.setTransform(state->matrix, true); -
449 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen)); -
450 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush)); -
451 p.setBackground(state->bgBrush); -
452 p.setBackgroundMode(state->bgMode); -
453 p.setBrushOrigin(state->brushOrigin); -
454 -
455 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing); -
456 p.setRenderHint(QPainter::SmoothPixmapTransform, -
457 state->renderHints & QPainter::SmoothPixmapTransform); -
458 -
459 p.drawPath(originalPath); -
460 -
461#ifndef QT_NO_DEBUG -
462 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0; -
463 if (do_fallback_overlay) { -
464 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied); -
465 QPainter pt(&block); -
466 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196)); -
467 pt.drawLine(0, 0, 8, 8); -
468 pt.end(); -
469 p.resetTransform(); -
470 p.setCompositionMode(QPainter::CompositionMode_SourceAtop); -
471 p.setOpacity(0.5); -
472 p.fillRect(0, 0, image.width(), image.height(), QBrush(block)); -
473 } -
474#endif -
475 -
476 p.end(); -
477 -
478 q->save(); -
479 state->matrix = QTransform(); -
480 if (extended) { -
481 extended->transformChanged(); -
482 } else { -
483 state->dirtyFlags |= QPaintEngine::DirtyTransform; -
484 updateState(state); -
485 } -
486 engine->drawImage(absPathRect, -
487 image, -
488 QRectF(0, 0, absPathRect.width(), absPathRect.height()), -
489 Qt::OrderedDither | Qt::OrderedAlphaDither); -
490 q->restore(); -
491} -
492 -
493void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op) -
494{ -
495 Q_Q(QPainter); -
496 -
497 q->setBackgroundMode(Qt::TransparentMode); -
498 -
499 if (op & FillDraw && state->brush.style() != Qt::NoBrush) { -
500 q->fillPath(path, state->bgBrush.color()); -
501 q->fillPath(path, state->brush); -
502 } -
503 -
504 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) { -
505 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width())); -
506 q->strokePath(path, state->pen); -
507 } -
508 -
509 q->setBackgroundMode(Qt::OpaqueMode); -
510} -
511 -
512static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect) -
513{ -
514 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern -
515 && brush.style() <= Qt::ConicalGradientPattern); -
516 -
517 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(), -
518 boundingRect.x(), boundingRect.y()); -
519 -
520 QGradient g = *brush.gradient(); -
521 g.setCoordinateMode(QGradient::LogicalMode); -
522 -
523 QBrush b(g); -
524 b.setTransform(gradientToUser * b.transform()); -
525 return b; -
526} -
527 -
528void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op) -
529{ -
530 Q_Q(QPainter); -
531 -
532 const qreal sw = helper_device->width(); -
533 const qreal sh = helper_device->height(); -
534 -
535 bool changedPen = false; -
536 bool changedBrush = false; -
537 bool needsFill = false; -
538 -
539 const QPen pen = state->pen; -
540 const QBrush brush = state->brush; -
541 -
542 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush()); -
543 const QGradient::CoordinateMode brushMode = coordinateMode(brush); -
544 -
545 QRectF boundingRect; -
546 -
547 // Draw the xformed fill if the brush is a stretch gradient. -
548 if ((op & FillDraw) && brush.style() != Qt::NoBrush) { -
549 if (brushMode == QGradient::StretchToDeviceMode) { -
550 q->setPen(Qt::NoPen); -
551 changedPen = pen.style() != Qt::NoPen; -
552 q->scale(sw, sh); -
553 updateState(state); -
554 -
555 const qreal isw = 1.0 / sw; -
556 const qreal ish = 1.0 / sh; -
557 QTransform inv(isw, 0, 0, ish, 0, 0); -
558 engine->drawPath(path * inv); -
559 q->scale(isw, ish); -
560 } else { -
561 needsFill = true; -
562 -
563 if (brushMode == QGradient::ObjectBoundingMode) { -
564 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform)); -
565 boundingRect = path.boundingRect(); -
566 q->setBrush(stretchGradientToUserSpace(brush, boundingRect)); -
567 changedBrush = true; -
568 } -
569 } -
570 } -
571 -
572 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) { -
573 // Draw the xformed outline if the pen is a stretch gradient. -
574 if (penMode == QGradient::StretchToDeviceMode) { -
575 q->setPen(Qt::NoPen); -
576 changedPen = true; -
577 -
578 if (needsFill) { -
579 updateState(state); -
580 engine->drawPath(path); -
581 } -
582 -
583 q->scale(sw, sh); -
584 q->setBrush(pen.brush()); -
585 changedBrush = true; -
586 updateState(state); -
587 -
588 QPainterPathStroker stroker; -
589 stroker.setDashPattern(pen.style()); -
590 stroker.setWidth(pen.widthF()); -
591 stroker.setJoinStyle(pen.joinStyle()); -
592 stroker.setCapStyle(pen.capStyle()); -
593 stroker.setMiterLimit(pen.miterLimit()); -
594 QPainterPath stroke = stroker.createStroke(path); -
595 -
596 const qreal isw = 1.0 / sw; -
597 const qreal ish = 1.0 / sh; -
598 QTransform inv(isw, 0, 0, ish, 0, 0); -
599 engine->drawPath(stroke * inv); -
600 q->scale(isw, ish); -
601 } else { -
602 if (!needsFill && brush.style() != Qt::NoBrush) { -
603 q->setBrush(Qt::NoBrush); -
604 changedBrush = true; -
605 } -
606 -
607 if (penMode == QGradient::ObjectBoundingMode) { -
608 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform)); -
609 -
610 // avoid computing the bounding rect twice -
611 if (!needsFill || brushMode != QGradient::ObjectBoundingMode) -
612 boundingRect = path.boundingRect(); -
613 -
614 QPen p = pen; -
615 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect)); -
616 q->setPen(p); -
617 changedPen = true; -
618 } else if (changedPen) { -
619 q->setPen(pen); -
620 changedPen = false; -
621 } -
622 -
623 updateState(state); -
624 engine->drawPath(path); -
625 } -
626 } else if (needsFill) { -
627 if (pen.style() != Qt::NoPen) { -
628 q->setPen(Qt::NoPen); -
629 changedPen = true; -
630 } -
631 -
632 updateState(state); -
633 engine->drawPath(path); -
634 } -
635 -
636 if (changedPen) -
637 q->setPen(pen); -
638 if (changedBrush) -
639 q->setBrush(brush); -
640} -
641 -
642 -
643void QPainterPrivate::updateMatrix() -
644{ -
645 state->matrix = state->WxF ? state->worldMatrix : QTransform(); -
646 if (state->VxF) -
647 state->matrix *= viewTransform(); -
648 -
649 txinv = false; // no inverted matrix -
650 state->matrix *= state->redirectionMatrix; -
651 if (extended) -
652 extended->transformChanged(); -
653 else -
654 state->dirtyFlags |= QPaintEngine::DirtyTransform; -
655 -
656 state->matrix *= hidpiScaleTransform(); -
657 -
658// printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF); -
659// qDebug() << " --- using matrix" << state->matrix << redirection_offset; -
660} -
661 -
662/*! \internal */ -
663void QPainterPrivate::updateInvMatrix() -
664{ -
665 Q_ASSERT(txinv == false); -
666 txinv = true; // creating inverted matrix -
667 invMatrix = state->matrix.inverted(); -
668} -
669 -
670extern bool qt_isExtendedRadialGradient(const QBrush &brush); -
671 -
672void QPainterPrivate::updateEmulationSpecifier(QPainterState *s) -
673{ -
674 bool alpha = false; -
675 bool linearGradient = false; -
676 bool radialGradient = false; -
677 bool extendedRadialGradient = false; -
678 bool conicalGradient = false; -
679 bool patternBrush = false; -
680 bool xform = false; -
681 bool complexXform = false; -
682 -
683 bool skip = true; -
684 -
685 // Pen and brush properties (we have to check both if one changes because the -
686 // one that's unchanged can still be in a state which requires emulation) -
687 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) { -
688 // Check Brush stroke emulation -
689 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke)) -
690 s->emulationSpecifier |= QPaintEngine::BrushStroke; -
691 else -
692 s->emulationSpecifier &= ~QPaintEngine::BrushStroke; -
693 -
694 skip = false; -
695 -
696 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen); -
697 Qt::BrushStyle brushStyle = qbrush_style(s->brush); -
698 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush); -
699 alpha = (penBrushStyle != Qt::NoBrush -
700 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255) -
701 && !penBrush.isOpaque()) -
702 || (brushStyle != Qt::NoBrush -
703 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255) -
704 && !s->brush.isOpaque()); -
705 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) || -
706 (brushStyle == Qt::LinearGradientPattern)); -
707 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) || -
708 (brushStyle == Qt::RadialGradientPattern)); -
709 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush)); -
710 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) || -
711 (brushStyle == Qt::ConicalGradientPattern)); -
712 patternBrush = (((penBrushStyle > Qt::SolidPattern -
713 && penBrushStyle < Qt::LinearGradientPattern) -
714 || penBrushStyle == Qt::TexturePattern) || -
715 ((brushStyle > Qt::SolidPattern -
716 && brushStyle < Qt::LinearGradientPattern) -
717 || brushStyle == Qt::TexturePattern)); -
718 -
719 bool penTextureAlpha = false; -
720 if (penBrush.style() == Qt::TexturePattern) -
721 penTextureAlpha = qHasPixmapTexture(penBrush) -
722 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha() -
723 : penBrush.textureImage().hasAlphaChannel(); -
724 bool brushTextureAlpha = false; -
725 if (s->brush.style() == Qt::TexturePattern) { -
726 brushTextureAlpha = qHasPixmapTexture(s->brush) -
727 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha() -
728 : s->brush.textureImage().hasAlphaChannel(); -
729 } -
730 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha) -
731 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha)) -
732 && !engine->hasFeature(QPaintEngine::MaskedBrush)) -
733 s->emulationSpecifier |= QPaintEngine::MaskedBrush; -
734 else -
735 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush; -
736 } -
737 -
738 if (s->state() & (QPaintEngine::DirtyHints -
739 | QPaintEngine::DirtyOpacity -
740 | QPaintEngine::DirtyBackgroundMode)) { -
741 skip = false; -
742 } -
743 -
744 if (skip) -
745 return; -
746 -
747#if 0 -
748 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n" -
749 " - alpha: %d\n" -
750 " - linearGradient: %d\n" -
751 " - radialGradient: %d\n" -
752 " - conicalGradient: %d\n" -
753 " - patternBrush: %d\n" -
754 " - hints: %x\n" -
755 " - xform: %d\n", -
756 s, -
757 alpha, -
758 linearGradient, -
759 radialGradient, -
760 conicalGradient, -
761 patternBrush, -
762 uint(s->renderHints), -
763 xform); -
764#endif -
765 -
766 // XForm properties -
767 if (s->state() & QPaintEngine::DirtyTransform) { -
768 xform = !s->matrix.isIdentity(); -
769 complexXform = !s->matrix.isAffine(); -
770 } else if (s->matrix.type() >= QTransform::TxTranslate) { -
771 xform = true; -
772 complexXform = !s->matrix.isAffine(); -
773 } -
774 -
775 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone); -
776 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone); -
777 -
778 const bool patternXform = patternBrush && (xform || brushXform || penXform); -
779 -
780 // Check alphablending -
781 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend)) -
782 s->emulationSpecifier |= QPaintEngine::AlphaBlend; -
783 else -
784 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend; -
785 -
786 // Linear gradient emulation -
787 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill)) -
788 s->emulationSpecifier |= QPaintEngine::LinearGradientFill; -
789 else -
790 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill; -
791 -
792 // Radial gradient emulation -
793 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill))) -
794 s->emulationSpecifier |= QPaintEngine::RadialGradientFill; -
795 else -
796 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill; -
797 -
798 // Conical gradient emulation -
799 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill)) -
800 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill; -
801 else -
802 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill; -
803 -
804 // Pattern brushes -
805 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush)) -
806 s->emulationSpecifier |= QPaintEngine::PatternBrush; -
807 else -
808 s->emulationSpecifier &= ~QPaintEngine::PatternBrush; -
809 -
810 // Pattern XForms -
811 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform)) -
812 s->emulationSpecifier |= QPaintEngine::PatternTransform; -
813 else -
814 s->emulationSpecifier &= ~QPaintEngine::PatternTransform; -
815 -
816 // Primitive XForms -
817 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform)) -
818 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform; -
819 else -
820 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform; -
821 -
822 // Perspective XForms -
823 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform)) -
824 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform; -
825 else -
826 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform; -
827 -
828 // Constant opacity -
829 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity)) -
830 s->emulationSpecifier |= QPaintEngine::ConstantOpacity; -
831 else -
832 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity; -
833 -
834 bool gradientStretch = false; -
835 bool objectBoundingMode = false; -
836 if (linearGradient || conicalGradient || radialGradient) { -
837 QGradient::CoordinateMode brushMode = coordinateMode(s->brush); -
838 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush()); -
839 -
840 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode); -
841 gradientStretch |= (penMode == QGradient::StretchToDeviceMode); -
842 -
843 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode); -
844 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode); -
845 } -
846 if (gradientStretch) -
847 s->emulationSpecifier |= QGradient_StretchToDevice; -
848 else -
849 s->emulationSpecifier &= ~QGradient_StretchToDevice; -
850 -
851 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients)) -
852 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients; -
853 else -
854 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients; -
855 -
856 // Opaque backgrounds... -
857 if (s->bgMode == Qt::OpaqueMode && -
858 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush))) -
859 s->emulationSpecifier |= QPaintEngine_OpaqueBackground; -
860 else -
861 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground; -
862 -
863#if 0 -
864 //won't be correct either way because the device can already have -
865 // something rendered to it in which case subsequent emulation -
866 // on a fully transparent qimage and then blitting the results -
867 // won't produce correct results -
868 // Blend modes -
869 if (state->composition_mode > QPainter::CompositionMode_Xor && -
870 !engine->hasFeature(QPaintEngine::BlendModes)) -
871 s->emulationSpecifier |= QPaintEngine::BlendModes; -
872 else -
873 s->emulationSpecifier &= ~QPaintEngine::BlendModes; -
874#endif -
875} -
876 -
877void QPainterPrivate::updateStateImpl(QPainterState *newState) -
878{ -
879 // ### we might have to call QPainter::begin() here... -
880 if (!engine->state) { -
881 engine->state = newState; -
882 engine->setDirty(QPaintEngine::AllDirty); -
883 } -
884 -
885 if (engine->state->painter() != newState->painter) -
886 // ### this could break with clip regions vs paths. -
887 engine->setDirty(QPaintEngine::AllDirty); -
888 -
889 // Upon restore, revert all changes since last save -
890 else if (engine->state != newState) -
891 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags); -
892 -
893 // We need to store all changes made so that restore can deal with them -
894 else -
895 newState->changeFlags |= newState->dirtyFlags; -
896 -
897 updateEmulationSpecifier(newState); -
898 -
899 // Unset potential dirty background mode -
900 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode -
901 | QPaintEngine::DirtyBackground); -
902 -
903 engine->state = newState; -
904 engine->updateState(*newState); -
905 engine->clearDirty(QPaintEngine::AllDirty); -
906 -
907} -
908 -
909void QPainterPrivate::updateState(QPainterState *newState) -
910{ -
911 -
912 if (!newState) { -
913 engine->state = newState; -
914 } else if (newState->state() || engine->state!=newState) { -
915 updateStateImpl(newState); -
916 } -
917} -
918 -
919 -
920/*!-
\class QPainter
\brief The QPainter class performs low-level painting on widgets and
other paint devices.
\inmodule QtGui
\ingroup painting
\reentrant
QPainter provides highly optimized functions to do most of the
drawing GUI programs require. It can draw everything from simple
lines to complex shapes like pies and chords. It can also draw
aligned text and pixmaps. Normally, it draws in a "natural"
coordinate system, but it can also do view and world
transformation. QPainter can operate on any object that inherits
the QPaintDevice class.
The common use of QPainter is inside a widget's paint event:
Construct and customize (e.g. set the pen or the brush) the
painter. Then draw. Remember to destroy the QPainter object after
drawing. For example:
\snippet code/src_gui_painting_qpainter.cpp 0
The core functionality of QPainter is drawing, but the class also
provide several functions that allows you to customize QPainter's
settings and its rendering quality, and others that enable
clipping. In addition you can control how different shapes are
merged together by specifying the painter's composition mode.
The isActive() function indicates whether the painter is active. A
painter is activated by the begin() function and the constructor
that takes a QPaintDevice argument. The end() function, and the
destructor, deactivates it.
Together with the QPaintDevice and QPaintEngine classes, QPainter
form the basis for Qt's paint system. QPainter is the class used
to perform drawing operations. QPaintDevice represents a device
that can be painted on using a QPainter. QPaintEngine provides the
interface that the painter uses to draw onto different types of
devices. If the painter is active, device() returns the paint
device on which the painter paints, and paintEngine() returns the
paint engine that the painter is currently operating on. For more
information, see the \l {Paint System}.
Sometimes it is desirable to make someone else paint on an unusual
QPaintDevice. QPainter supports a static function to do this,
setRedirected().
\warning When the paintdevice is a widget, QPainter can only be
used inside a paintEvent() function or in a function called by
paintEvent().
\tableofcontents
\section1 Settings
There are several settings that you can customize to make QPainter
draw according to your preferences:
\list
\li font() is the font used for drawing text. If the painter
isActive(), you can retrieve information about the currently set
font, and its metrics, using the fontInfo() and fontMetrics()
functions respectively.
\li brush() defines the color or pattern that is used for filling
shapes.
\li pen() defines the color or stipple that is used for drawing
lines or boundaries.
\li backgroundMode() defines whether there is a background() or
not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
\li background() only applies when backgroundMode() is \l
Qt::OpaqueMode and pen() is a stipple. In that case, it
describes the color of the background pixels in the stipple.
\li brushOrigin() defines the origin of the tiled brushes, normally
the origin of widget's background.
\li viewport(), window(), worldTransform() make up the painter's coordinate
transformation system. For more information, see the \l
{Coordinate Transformations} section and the \l {Coordinate
System} documentation.
\li hasClipping() tells whether the painter clips at all. (The paint
device clips, too.) If the painter clips, it clips to clipRegion().
\li layoutDirection() defines the layout direction used by the
painter when drawing text.
\li worldMatrixEnabled() tells whether world transformation is enabled.
\li viewTransformEnabled() tells whether view transformation is
enabled.
\endlist
Note that some of these settings mirror settings in some paint
devices, e.g. QWidget::font(). The QPainter::begin() function (or
equivalently the QPainter constructor) copies these attributes
from the paint device.
You can at any time save the QPainter's state by calling the
save() function which saves all the available settings on an
internal stack. The restore() function pops them back.
\section1 Drawing
QPainter provides functions to draw most primitives: drawPoint(),
drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
convenience functions, drawRects() and drawLines(), draw the given
number of rectangles or lines in the given array of \l
{QRect}{QRects} or \l {QLine}{QLines} using the current pen and
brush.
The QPainter class also provides the fillRect() function which
fills the given QRect, with the given QBrush, and the eraseRect()
function that erases the area inside the given rectangle.
All of these functions have both integer and floating point
versions.
\table 100%
\row
\li \inlineimage qpainter-basicdrawing.png
\li
\b {Basic Drawing Example}
The \l {painting/basicdrawing}{Basic Drawing} example shows how to
display basic graphics primitives in a variety of styles using the
QPainter class.
\endtable
If you need to draw a complex shape, especially if you need to do
so repeatedly, consider creating a QPainterPath and drawing it
using drawPath().
\table 100%
\row
\li
\b {Painter Paths example}
The QPainterPath class provides a container for painting
operations, enabling graphical shapes to be constructed and
reused.
The \l {painting/painterpaths}{Painter Paths} example shows how
painter paths can be used to build complex shapes for rendering.
\li \inlineimage qpainter-painterpaths.png
\endtable
QPainter also provides the fillPath() function which fills the
given QPainterPath with the given QBrush, and the strokePath()
function that draws the outline of the given path (i.e. strokes
the path).
See also the \l {painting/deform}{Vector Deformation} example which
shows how to use advanced vector techniques to draw text using a
QPainterPath, the \l {painting/gradients}{Gradients} example which shows
the different types of gradients that are available in Qt, and the \l
{painting/pathstroke}{Path Stroking} example which shows Qt's built-in
dash patterns and shows how custom patterns can be used to extend
the range of available patterns.
\table
\header
\li \l {painting/deform}{Vector Deformation}
\li \l {painting/gradients}{Gradients}
\li \l {painting/pathstroke}{Path Stroking}
\row
\li \inlineimage qpainter-vectordeformation.png
\li \inlineimage qpainter-gradients.png
\li \inlineimage qpainter-pathstroking.png
\endtable
There are functions to draw pixmaps/images, namely drawPixmap(),
drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
produce the same result, except that drawPixmap() is faster
on-screen while drawImage() may be faster on a QPrinter or other
devices.
Text drawing is done using drawText(). When you need
fine-grained positioning, boundingRect() tells you where a given
drawText() command will draw.
There is a drawPicture() function that draws the contents of an
entire QPicture. The drawPicture() function is the only function
that disregards all the painter's settings as QPicture has its own
settings.
\section1 Rendering Quality
To get the optimal rendering result using QPainter, you should use
the platform independent QImage as paint device; i.e. using QImage
will ensure that the result has an identical pixel representation
on any platform.
The QPainter class also provides a means of controlling the
rendering quality through its RenderHint enum and the support for
floating point precision: All the functions for drawing primitives
has a floating point version. These are often used in combination
with the \l {RenderHint}{QPainter::Antialiasing} render hint.
\table 100%
\row
\li \inlineimage qpainter-concentriccircles.png
\li
\b {Concentric Circles Example}
The \l {painting/concentriccircles}{Concentric Circles} example
shows the improved rendering quality that can be obtained using
floating point precision and anti-aliasing when drawing custom
widgets.
The application's main window displays several widgets which are
drawn using the various combinations of precision and
anti-aliasing.
\endtable
The RenderHint enum specifies flags to QPainter that may or may
not be respected by any given engine. \l
{RenderHint}{QPainter::Antialiasing} indicates that the engine
should antialias edges of primitives if possible, \l
{RenderHint}{QPainter::TextAntialiasing} indicates that the engine
should antialias text if possible, and the \l
{RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
engine should use a smooth pixmap transformation algorithm.
\l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
indicating that the engine should use fragment programs and offscreen
rendering for antialiasing.
The renderHints() function returns a flag that specifies the
rendering hints that are set for this painter. Use the
setRenderHint() function to set or clear the currently set
RenderHints.
\section1 Coordinate Transformations
Normally, the QPainter operates on the device's own coordinate
system (usually pixels), but QPainter has good support for
coordinate transformations.
\table
\header
\li nop \li rotate() \li scale() \li translate()
\row
\li \inlineimage qpainter-clock.png
\li \inlineimage qpainter-rotation.png
\li \inlineimage qpainter-scale.png
\li \inlineimage qpainter-translation.png
\endtable
The most commonly used transformations are scaling, rotation,
translation and shearing. Use the scale() function to scale the
coordinate system by a given offset, the rotate() function to
rotate it clockwise and translate() to translate it (i.e. adding a
given offset to the points). You can also twist the coordinate
system around the origin using the shear() function. See the \l
{painting/affine}{Affine Transformations} example for a visualization of
a sheared coordinate system.
See also the \l {painting/transformations}{Transformations}
example which shows how transformations influence the way that
QPainter renders graphics primitives. In particular it shows how
the order of transformations affects the result.
\table 100%
\row
\li
\b {Affine Transformations Example}
The \l {painting/affine}{Affine Transformations} example shows Qt's
ability to perform affine transformations on painting
operations. The demo also allows the user to experiment with the
transformation operations and see the results immediately.
\li \inlineimage qpainter-affinetransformations.png
\endtable
All the tranformation operations operate on the transformation
worldTransform(). A matrix transforms a point in the plane to another
point. For more information about the transformation matrix, see
the \l {Coordinate System} and QTransform documentation.
The setWorldTransform() function can replace or add to the currently
set worldTransform(). The resetTransform() function resets any
transformations that were made using translate(), scale(),
shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
functions. The deviceTransform() returns the matrix that transforms
from logical coordinates to device coordinates of the platform
dependent paint device. The latter function is only needed when
using platform painting commands on the platform dependent handle,
and the platform does not do transformations nativly.
When drawing with QPainter, we specify points using logical
coordinates which then are converted into the physical coordinates
of the paint device. The mapping of the logical coordinates to the
physical coordinates are handled by QPainter's combinedTransform(), a
combination of viewport() and window() and worldTransform(). The
viewport() represents the physical coordinates specifying an
arbitrary rectangle, the window() describes the same rectangle in
logical coordinates, and the worldTransform() is identical with the
transformation matrix.
See also \l {Coordinate System}
\section1 Clipping
QPainter can clip any drawing operation to a rectangle, a region,
or a vector path. The current clip is available using the
functions clipRegion() and clipPath(). Whether paths or regions are
preferred (faster) depends on the underlying paintEngine(). For
example, the QImage paint engine prefers paths while the X11 paint
engine prefers regions. Setting a clip is done in the painters
logical coordinates.
After QPainter's clipping, the paint device may also clip. For
example, most widgets clip away the pixels used by child widgets,
and most printers clip away an area near the edges of the paper.
This additional clipping is not reflected by the return value of
clipRegion() or hasClipping().
\section1 Composition Modes
\target Composition Modes
QPainter provides the CompositionMode enum which defines the
Porter-Duff rules for digital image compositing; it describes a
model for combining the pixels in one image, the source, with the
pixels in another image, the destination.
The two most common forms of composition are \l
{QPainter::CompositionMode}{Source} and \l
{QPainter::CompositionMode}{SourceOver}. \l
{QPainter::CompositionMode}{Source} is used to draw opaque objects
onto a paint device. In this mode, each pixel in the source
replaces the corresponding pixel in the destination. In \l
{QPainter::CompositionMode}{SourceOver} composition mode, the
source object is transparent and is drawn on top of the
destination.
Note that composition transformation operates pixelwise. For that
reason, there is a difference between using the graphic primitive
itself and its bounding rectangle: The bounding rect contains
pixels with alpha == 0 (i.e the pixels surrounding the
primitive). These pixels will overwrite the other image's pixels,
affectively clearing those, while the primitive only overwrites
its own area.
\table 100%
\row
\li \inlineimage qpainter-compositiondemo.png
\li
\b {Composition Modes Example}
The \l {painting/composition}{Composition Modes} example, available in
Qt's examples directory, allows you to experiment with the various
composition modes and see the results immediately.
\endtable
\section1 Limitations
\target Limitations
If you are using coordinates with Qt's raster-based paint engine, it is
important to note that, while coordinates greater than +/- 2\sup 15 can
be used, any painting performed with coordinates outside this range is not
guaranteed to be shown; the drawing may be clipped. This is due to the
use of \c{short int} in the implementation.
The outlines generated by Qt's stroker are only an approximation when dealing
with curved shapes. It is in most cases impossible to represent the outline of
a bezier curve segment using another bezier curve segment, and so Qt approximates
the curve outlines by using several smaller curves. For performance reasons there
is a limit to how many curves Qt uses for these outlines, and thus when using
large pen widths or scales the outline error increases. To generate outlines with
smaller errors it is possible to use the QPainterPathStroker class, which has the
setCurveThreshold member function which let's the user specify the error tolerance.
Another workaround is to convert the paths to polygons first and then draw the
polygons instead.
\section1 Performance
QPainter is a rich framework that allows developers to do a great
variety of graphical operations, such as gradients, composition
modes and vector graphics. And QPainter can do this across a
variety of different hardware and software stacks. Naturally the
underlying combination of hardware and software has some
implications for performance, and ensuring that every single
operation is fast in combination with all the various combinations
of composition modes, brushes, clipping, transformation, etc, is
close to an impossible task because of the number of
permutations. As a compromise we have selected a subset of the
QPainter API and backends, where performance is guaranteed to be as
good as we can sensibly get it for the given combination of
hardware and software.
The backends we focus on as high-performance engines are:
\list
\li Raster - This backend implements all rendering in pure software
and is always used to render into QImages. For optimal performance
only use the format types QImage::Format_ARGB32_Premultiplied,
QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
including QImage::Format_ARGB32, has significantly worse
performance. This engine is used by default for QWidget and QPixmap.
\li OpenGL 2.0 (ES) - This backend is the primary backend for
hardware accelerated graphics. It can be run on desktop machines
and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
specification. This includes most graphics chips produced in the
last couple of years. The engine can be enabled by using QPainter
onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the
command line when the underlying system supports it.
\li OpenVG - This backend implements the Khronos standard for 2D
and Vector Graphics. It is primarily for embedded devices with
hardware support for OpenVG. The engine can be enabled by
passing \c {-graphicssystem openvg} on the command line when
the underlying system supports it.
\endlist
These operations are:
\list
\li Simple transformations, meaning translation and scaling, pluss
0, 90, 180, 270 degree rotations.
\li \c drawPixmap() in combination with simple transformations and
opacity with non-smooth transformation mode
(\c QPainter::SmoothPixmapTransform not enabled as a render hint).
\li Rectangle fills with solid color, two-color linear gradients
and simple transforms.
\li Rectangular clipping with simple transformations and intersect
clip.
\li Composition Modes \c QPainter::CompositionMode_Source and
QPainter::CompositionMode_SourceOver
\li Rounded rectangle filling using solid color and two-color
linear gradients fills.
\li 3x3 patched pixmaps, via qDrawBorderPixmap.
\endlist
This list gives an indication of which features to safely use in
an application where performance is critical. For certain setups,
other operations may be fast too, but before making extensive use
of them, it is recommended to benchmark and verify them on the
system where the software will run in the end. There are also
cases where expensive operations are ok to use, for instance when
the result is cached in a QPixmap.
\sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
{Drawing Utility Functions}
*/*!
921 \class QPainter -
922 \brief The QPainter class performs low-level painting on widgets and -
923 other paint devices. -
924 -
925 \inmodule QtGui -
926 \ingroup painting -
927 -
928 \reentrant -
929 -
930 QPainter provides highly optimized functions to do most of the -
931 drawing GUI programs require. It can draw everything from simple -
932 lines to complex shapes like pies and chords. It can also draw -
933 aligned text and pixmaps. Normally, it draws in a "natural" -
934 coordinate system, but it can also do view and world -
935 transformation. QPainter can operate on any object that inherits -
936 the QPaintDevice class. -
937 -
938 The common use of QPainter is inside a widget's paint event: -
939 Construct and customize (e.g. set the pen or the brush) the -
940 painter. Then draw. Remember to destroy the QPainter object after -
941 drawing. For example: -
942 -
943 \snippet code/src_gui_painting_qpainter.cpp 0 -
944 -
945 The core functionality of QPainter is drawing, but the class also -
946 provide several functions that allows you to customize QPainter's -
947 settings and its rendering quality, and others that enable -
948 clipping. In addition you can control how different shapes are -
949 merged together by specifying the painter's composition mode. -
950 -
951 The isActive() function indicates whether the painter is active. A -
952 painter is activated by the begin() function and the constructor -
953 that takes a QPaintDevice argument. The end() function, and the -
954 destructor, deactivates it. -
955 -
956 Together with the QPaintDevice and QPaintEngine classes, QPainter -
957 form the basis for Qt's paint system. QPainter is the class used -
958 to perform drawing operations. QPaintDevice represents a device -
959 that can be painted on using a QPainter. QPaintEngine provides the -
960 interface that the painter uses to draw onto different types of -
961 devices. If the painter is active, device() returns the paint -
962 device on which the painter paints, and paintEngine() returns the -
963 paint engine that the painter is currently operating on. For more -
964 information, see the \l {Paint System}. -
965 -
966 Sometimes it is desirable to make someone else paint on an unusual -
967 QPaintDevice. QPainter supports a static function to do this, -
968 setRedirected(). -
969 -
970 \warning When the paintdevice is a widget, QPainter can only be -
971 used inside a paintEvent() function or in a function called by -
972 paintEvent(). -
973 -
974 \tableofcontents -
975 -
976 \section1 Settings -
977 -
978 There are several settings that you can customize to make QPainter -
979 draw according to your preferences: -
980 -
981 \list -
982 -
983 \li font() is the font used for drawing text. If the painter -
984 isActive(), you can retrieve information about the currently set -
985 font, and its metrics, using the fontInfo() and fontMetrics() -
986 functions respectively. -
987 -
988 \li brush() defines the color or pattern that is used for filling -
989 shapes. -
990 -
991 \li pen() defines the color or stipple that is used for drawing -
992 lines or boundaries. -
993 -
994 \li backgroundMode() defines whether there is a background() or -
995 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode. -
996 -
997 \li background() only applies when backgroundMode() is \l -
998 Qt::OpaqueMode and pen() is a stipple. In that case, it -
999 describes the color of the background pixels in the stipple. -
1000 -
1001 \li brushOrigin() defines the origin of the tiled brushes, normally -
1002 the origin of widget's background. -
1003 -
1004 \li viewport(), window(), worldTransform() make up the painter's coordinate -
1005 transformation system. For more information, see the \l -
1006 {Coordinate Transformations} section and the \l {Coordinate -
1007 System} documentation. -
1008 -
1009 \li hasClipping() tells whether the painter clips at all. (The paint -
1010 device clips, too.) If the painter clips, it clips to clipRegion(). -
1011 -
1012 \li layoutDirection() defines the layout direction used by the -
1013 painter when drawing text. -
1014 -
1015 \li worldMatrixEnabled() tells whether world transformation is enabled. -
1016 -
1017 \li viewTransformEnabled() tells whether view transformation is -
1018 enabled. -
1019 -
1020 \endlist -
1021 -
1022 Note that some of these settings mirror settings in some paint -
1023 devices, e.g. QWidget::font(). The QPainter::begin() function (or -
1024 equivalently the QPainter constructor) copies these attributes -
1025 from the paint device. -
1026 -
1027 You can at any time save the QPainter's state by calling the -
1028 save() function which saves all the available settings on an -
1029 internal stack. The restore() function pops them back. -
1030 -
1031 \section1 Drawing -
1032 -
1033 QPainter provides functions to draw most primitives: drawPoint(), -
1034 drawPoints(), drawLine(), drawRect(), drawRoundedRect(), -
1035 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(), -
1036 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two -
1037 convenience functions, drawRects() and drawLines(), draw the given -
1038 number of rectangles or lines in the given array of \l -
1039 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and -
1040 brush. -
1041 -
1042 The QPainter class also provides the fillRect() function which -
1043 fills the given QRect, with the given QBrush, and the eraseRect() -
1044 function that erases the area inside the given rectangle. -
1045 -
1046 All of these functions have both integer and floating point -
1047 versions. -
1048 -
1049 \table 100% -
1050 \row -
1051 \li \inlineimage qpainter-basicdrawing.png -
1052 \li -
1053 \b {Basic Drawing Example} -
1054 -
1055 The \l {painting/basicdrawing}{Basic Drawing} example shows how to -
1056 display basic graphics primitives in a variety of styles using the -
1057 QPainter class. -
1058 -
1059 \endtable -
1060 -
1061 If you need to draw a complex shape, especially if you need to do -
1062 so repeatedly, consider creating a QPainterPath and drawing it -
1063 using drawPath(). -
1064 -
1065 \table 100% -
1066 \row -
1067 \li -
1068 \b {Painter Paths example} -
1069 -
1070 The QPainterPath class provides a container for painting -
1071 operations, enabling graphical shapes to be constructed and -
1072 reused. -
1073 -
1074 The \l {painting/painterpaths}{Painter Paths} example shows how -
1075 painter paths can be used to build complex shapes for rendering. -
1076 -
1077 \li \inlineimage qpainter-painterpaths.png -
1078 \endtable -
1079 -
1080 QPainter also provides the fillPath() function which fills the -
1081 given QPainterPath with the given QBrush, and the strokePath() -
1082 function that draws the outline of the given path (i.e. strokes -
1083 the path). -
1084 -
1085 See also the \l {painting/deform}{Vector Deformation} example which -
1086 shows how to use advanced vector techniques to draw text using a -
1087 QPainterPath, the \l {painting/gradients}{Gradients} example which shows -
1088 the different types of gradients that are available in Qt, and the \l -
1089 {painting/pathstroke}{Path Stroking} example which shows Qt's built-in -
1090 dash patterns and shows how custom patterns can be used to extend -
1091 the range of available patterns. -
1092 -
1093 \table -
1094 \header -
1095 \li \l {painting/deform}{Vector Deformation} -
1096 \li \l {painting/gradients}{Gradients} -
1097 \li \l {painting/pathstroke}{Path Stroking} -
1098 \row -
1099 \li \inlineimage qpainter-vectordeformation.png -
1100 \li \inlineimage qpainter-gradients.png -
1101 \li \inlineimage qpainter-pathstroking.png -
1102 \endtable -
1103 -
1104 -
1105 There are functions to draw pixmaps/images, namely drawPixmap(), -
1106 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage() -
1107 produce the same result, except that drawPixmap() is faster -
1108 on-screen while drawImage() may be faster on a QPrinter or other -
1109 devices. -
1110 -
1111 Text drawing is done using drawText(). When you need -
1112 fine-grained positioning, boundingRect() tells you where a given -
1113 drawText() command will draw. -
1114 -
1115 There is a drawPicture() function that draws the contents of an -
1116 entire QPicture. The drawPicture() function is the only function -
1117 that disregards all the painter's settings as QPicture has its own -
1118 settings. -
1119 -
1120 \section1 Rendering Quality -
1121 -
1122 To get the optimal rendering result using QPainter, you should use -
1123 the platform independent QImage as paint device; i.e. using QImage -
1124 will ensure that the result has an identical pixel representation -
1125 on any platform. -
1126 -
1127 The QPainter class also provides a means of controlling the -
1128 rendering quality through its RenderHint enum and the support for -
1129 floating point precision: All the functions for drawing primitives -
1130 has a floating point version. These are often used in combination -
1131 with the \l {RenderHint}{QPainter::Antialiasing} render hint. -
1132 -
1133 \table 100% -
1134 \row -
1135 \li \inlineimage qpainter-concentriccircles.png -
1136 \li -
1137 \b {Concentric Circles Example} -
1138 -
1139 The \l {painting/concentriccircles}{Concentric Circles} example -
1140 shows the improved rendering quality that can be obtained using -
1141 floating point precision and anti-aliasing when drawing custom -
1142 widgets. -
1143 -
1144 The application's main window displays several widgets which are -
1145 drawn using the various combinations of precision and -
1146 anti-aliasing. -
1147 -
1148 \endtable -
1149 -
1150 The RenderHint enum specifies flags to QPainter that may or may -
1151 not be respected by any given engine. \l -
1152 {RenderHint}{QPainter::Antialiasing} indicates that the engine -
1153 should antialias edges of primitives if possible, \l -
1154 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine -
1155 should antialias text if possible, and the \l -
1156 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the -
1157 engine should use a smooth pixmap transformation algorithm. -
1158 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint -
1159 indicating that the engine should use fragment programs and offscreen -
1160 rendering for antialiasing. -
1161 -
1162 The renderHints() function returns a flag that specifies the -
1163 rendering hints that are set for this painter. Use the -
1164 setRenderHint() function to set or clear the currently set -
1165 RenderHints. -
1166 -
1167 \section1 Coordinate Transformations -
1168 -
1169 Normally, the QPainter operates on the device's own coordinate -
1170 system (usually pixels), but QPainter has good support for -
1171 coordinate transformations. -
1172 -
1173 \table -
1174 \header -
1175 \li nop \li rotate() \li scale() \li translate() -
1176 \row -
1177 \li \inlineimage qpainter-clock.png -
1178 \li \inlineimage qpainter-rotation.png -
1179 \li \inlineimage qpainter-scale.png -
1180 \li \inlineimage qpainter-translation.png -
1181 \endtable -
1182 -
1183 The most commonly used transformations are scaling, rotation, -
1184 translation and shearing. Use the scale() function to scale the -
1185 coordinate system by a given offset, the rotate() function to -
1186 rotate it clockwise and translate() to translate it (i.e. adding a -
1187 given offset to the points). You can also twist the coordinate -
1188 system around the origin using the shear() function. See the \l -
1189 {painting/affine}{Affine Transformations} example for a visualization of -
1190 a sheared coordinate system. -
1191 -
1192 See also the \l {painting/transformations}{Transformations} -
1193 example which shows how transformations influence the way that -
1194 QPainter renders graphics primitives. In particular it shows how -
1195 the order of transformations affects the result. -
1196 -
1197 \table 100% -
1198 \row -
1199 \li -
1200 \b {Affine Transformations Example} -
1201 -
1202 The \l {painting/affine}{Affine Transformations} example shows Qt's -
1203 ability to perform affine transformations on painting -
1204 operations. The demo also allows the user to experiment with the -
1205 transformation operations and see the results immediately. -
1206 -
1207 \li \inlineimage qpainter-affinetransformations.png -
1208 \endtable -
1209 -
1210 All the tranformation operations operate on the transformation -
1211 worldTransform(). A matrix transforms a point in the plane to another -
1212 point. For more information about the transformation matrix, see -
1213 the \l {Coordinate System} and QTransform documentation. -
1214 -
1215 The setWorldTransform() function can replace or add to the currently -
1216 set worldTransform(). The resetTransform() function resets any -
1217 transformations that were made using translate(), scale(), -
1218 shear(), rotate(), setWorldTransform(), setViewport() and setWindow() -
1219 functions. The deviceTransform() returns the matrix that transforms -
1220 from logical coordinates to device coordinates of the platform -
1221 dependent paint device. The latter function is only needed when -
1222 using platform painting commands on the platform dependent handle, -
1223 and the platform does not do transformations nativly. -
1224 -
1225 When drawing with QPainter, we specify points using logical -
1226 coordinates which then are converted into the physical coordinates -
1227 of the paint device. The mapping of the logical coordinates to the -
1228 physical coordinates are handled by QPainter's combinedTransform(), a -
1229 combination of viewport() and window() and worldTransform(). The -
1230 viewport() represents the physical coordinates specifying an -
1231 arbitrary rectangle, the window() describes the same rectangle in -
1232 logical coordinates, and the worldTransform() is identical with the -
1233 transformation matrix. -
1234 -
1235 See also \l {Coordinate System} -
1236 -
1237 \section1 Clipping -
1238 -
1239 QPainter can clip any drawing operation to a rectangle, a region, -
1240 or a vector path. The current clip is available using the -
1241 functions clipRegion() and clipPath(). Whether paths or regions are -
1242 preferred (faster) depends on the underlying paintEngine(). For -
1243 example, the QImage paint engine prefers paths while the X11 paint -
1244 engine prefers regions. Setting a clip is done in the painters -
1245 logical coordinates. -
1246 -
1247 After QPainter's clipping, the paint device may also clip. For -
1248 example, most widgets clip away the pixels used by child widgets, -
1249 and most printers clip away an area near the edges of the paper. -
1250 This additional clipping is not reflected by the return value of -
1251 clipRegion() or hasClipping(). -
1252 -
1253 \section1 Composition Modes -
1254 \target Composition Modes -
1255 -
1256 QPainter provides the CompositionMode enum which defines the -
1257 Porter-Duff rules for digital image compositing; it describes a -
1258 model for combining the pixels in one image, the source, with the -
1259 pixels in another image, the destination. -
1260 -
1261 The two most common forms of composition are \l -
1262 {QPainter::CompositionMode}{Source} and \l -
1263 {QPainter::CompositionMode}{SourceOver}. \l -
1264 {QPainter::CompositionMode}{Source} is used to draw opaque objects -
1265 onto a paint device. In this mode, each pixel in the source -
1266 replaces the corresponding pixel in the destination. In \l -
1267 {QPainter::CompositionMode}{SourceOver} composition mode, the -
1268 source object is transparent and is drawn on top of the -
1269 destination. -
1270 -
1271 Note that composition transformation operates pixelwise. For that -
1272 reason, there is a difference between using the graphic primitive -
1273 itself and its bounding rectangle: The bounding rect contains -
1274 pixels with alpha == 0 (i.e the pixels surrounding the -
1275 primitive). These pixels will overwrite the other image's pixels, -
1276 affectively clearing those, while the primitive only overwrites -
1277 its own area. -
1278 -
1279 \table 100% -
1280 \row -
1281 \li \inlineimage qpainter-compositiondemo.png -
1282 -
1283 \li -
1284 \b {Composition Modes Example} -
1285 -
1286 The \l {painting/composition}{Composition Modes} example, available in -
1287 Qt's examples directory, allows you to experiment with the various -
1288 composition modes and see the results immediately. -
1289 -
1290 \endtable -
1291 -
1292 \section1 Limitations -
1293 \target Limitations -
1294 -
1295 If you are using coordinates with Qt's raster-based paint engine, it is -
1296 important to note that, while coordinates greater than +/- 2\sup 15 can -
1297 be used, any painting performed with coordinates outside this range is not -
1298 guaranteed to be shown; the drawing may be clipped. This is due to the -
1299 use of \c{short int} in the implementation. -
1300 -
1301 The outlines generated by Qt's stroker are only an approximation when dealing -
1302 with curved shapes. It is in most cases impossible to represent the outline of -
1303 a bezier curve segment using another bezier curve segment, and so Qt approximates -
1304 the curve outlines by using several smaller curves. For performance reasons there -
1305 is a limit to how many curves Qt uses for these outlines, and thus when using -
1306 large pen widths or scales the outline error increases. To generate outlines with -
1307 smaller errors it is possible to use the QPainterPathStroker class, which has the -
1308 setCurveThreshold member function which let's the user specify the error tolerance. -
1309 Another workaround is to convert the paths to polygons first and then draw the -
1310 polygons instead. -
1311 -
1312 \section1 Performance -
1313 -
1314 QPainter is a rich framework that allows developers to do a great -
1315 variety of graphical operations, such as gradients, composition -
1316 modes and vector graphics. And QPainter can do this across a -
1317 variety of different hardware and software stacks. Naturally the -
1318 underlying combination of hardware and software has some -
1319 implications for performance, and ensuring that every single -
1320 operation is fast in combination with all the various combinations -
1321 of composition modes, brushes, clipping, transformation, etc, is -
1322 close to an impossible task because of the number of -
1323 permutations. As a compromise we have selected a subset of the -
1324 QPainter API and backends, where performance is guaranteed to be as -
1325 good as we can sensibly get it for the given combination of -
1326 hardware and software. -
1327 -
1328 The backends we focus on as high-performance engines are: -
1329 -
1330 \list -
1331 -
1332 \li Raster - This backend implements all rendering in pure software -
1333 and is always used to render into QImages. For optimal performance -
1334 only use the format types QImage::Format_ARGB32_Premultiplied, -
1335 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format, -
1336 including QImage::Format_ARGB32, has significantly worse -
1337 performance. This engine is used by default for QWidget and QPixmap. -
1338 -
1339 \li OpenGL 2.0 (ES) - This backend is the primary backend for -
1340 hardware accelerated graphics. It can be run on desktop machines -
1341 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0 -
1342 specification. This includes most graphics chips produced in the -
1343 last couple of years. The engine can be enabled by using QPainter -
1344 onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the -
1345 command line when the underlying system supports it. -
1346 -
1347 \li OpenVG - This backend implements the Khronos standard for 2D -
1348 and Vector Graphics. It is primarily for embedded devices with -
1349 hardware support for OpenVG. The engine can be enabled by -
1350 passing \c {-graphicssystem openvg} on the command line when -
1351 the underlying system supports it. -
1352 -
1353 \endlist -
1354 -
1355 These operations are: -
1356 -
1357 \list -
1358 -
1359 \li Simple transformations, meaning translation and scaling, pluss -
1360 0, 90, 180, 270 degree rotations. -
1361 -
1362 \li \c drawPixmap() in combination with simple transformations and -
1363 opacity with non-smooth transformation mode -
1364 (\c QPainter::SmoothPixmapTransform not enabled as a render hint). -
1365 -
1366 \li Rectangle fills with solid color, two-color linear gradients -
1367 and simple transforms. -
1368 -
1369 \li Rectangular clipping with simple transformations and intersect -
1370 clip. -
1371 -
1372 \li Composition Modes \c QPainter::CompositionMode_Source and -
1373 QPainter::CompositionMode_SourceOver -
1374 -
1375 \li Rounded rectangle filling using solid color and two-color -
1376 linear gradients fills. -
1377 -
1378 \li 3x3 patched pixmaps, via qDrawBorderPixmap. -
1379 -
1380 \endlist -
1381 -
1382 This list gives an indication of which features to safely use in -
1383 an application where performance is critical. For certain setups, -
1384 other operations may be fast too, but before making extensive use -
1385 of them, it is recommended to benchmark and verify them on the -
1386 system where the software will run in the end. There are also -
1387 cases where expensive operations are ok to use, for instance when -
1388 the result is cached in a QPixmap. -
1389 -
1390 \sa QPaintDevice, QPaintEngine, {Qt SVG}, {Basic Drawing Example}, -
1391 {Drawing Utility Functions} -
1392*/ -
1393 -
1394/*! -
1395 \enum QPainter::RenderHint -
1396 -
1397 Renderhints are used to specify flags to QPainter that may or -
1398 may not be respected by any given engine. -
1399 -
1400 \value Antialiasing Indicates that the engine should antialias -
1401 edges of primitives if possible. -
1402 -
1403 \value TextAntialiasing Indicates that the engine should antialias -
1404 text if possible. To forcibly disable antialiasing for text, do not -
1405 use this hint. Instead, set QFont::NoAntialias on your font's style -
1406 strategy. -
1407 -
1408 \value SmoothPixmapTransform Indicates that the engine should use -
1409 a smooth pixmap transformation algorithm (such as bilinear) rather -
1410 than nearest neighbor. -
1411 -
1412 \value HighQualityAntialiasing An OpenGL-specific rendering hint -
1413 indicating that the engine should use fragment programs and offscreen -
1414 rendering for antialiasing. -
1415 -
1416 \value NonCosmeticDefaultPen This value is obsolete, the default for QPen -
1417 is now non-cosmetic. -
1418 -
1419 \value Qt4CompatiblePainting Compatibility hint telling the engine to use the -
1420 same X11 based fill rules as in Qt 4, where aliased rendering is offset -
1421 by slightly less than half a pixel. Also will treat default constructed pens -
1422 as cosmetic. Potentially useful when porting a Qt 4 application to Qt 5. -
1423 -
1424 \sa renderHints(), setRenderHint(), {QPainter#Rendering -
1425 Quality}{Rendering Quality}, {Concentric Circles Example} -
1426 -
1427*/ -
1428 -
1429/*! -
1430 Constructs a painter. -
1431 -
1432 \sa begin(), end() -
1433*/ -
1434 -
1435QPainter::QPainter() -
1436 : d_ptr(new QPainterPrivate(this)) -
1437{ -
1438} -
1439 -
1440/*! -
1441 \fn QPainter::QPainter(QPaintDevice *device) -
1442 -
1443 Constructs a painter that begins painting the paint \a device -
1444 immediately. -
1445 -
1446 This constructor is convenient for short-lived painters, e.g. in a -
1447 QWidget::paintEvent() and should be used only once. The -
1448 constructor calls begin() for you and the QPainter destructor -
1449 automatically calls end(). -
1450 -
1451 Here's an example using begin() and end(): -
1452 \snippet code/src_gui_painting_qpainter.cpp 1 -
1453 -
1454 The same example using this constructor: -
1455 \snippet code/src_gui_painting_qpainter.cpp 2 -
1456 -
1457 Since the constructor cannot provide feedback when the initialization -
1458 of the painter failed you should rather use begin() and end() to paint -
1459 on external devices, e.g. printers. -
1460 -
1461 \sa begin(), end() -
1462*/ -
1463 -
1464QPainter::QPainter(QPaintDevice *pd) -
1465 : d_ptr(0) -
1466{ -
1467 Q_ASSERT(pd != 0); -
1468 if (!QPainterPrivate::attachPainterPrivate(this, pd)) { -
1469 d_ptr.reset(new QPainterPrivate(this)); -
1470 begin(pd); -
1471 } -
1472 Q_ASSERT(d_ptr); -
1473} -
1474 -
1475/*! -
1476 Destroys the painter. -
1477*/ -
1478QPainter::~QPainter() -
1479{ -
1480 d_ptr->inDestructor = true; -
1481 QT_TRY { -
1482 if (isActive()) -
1483 end(); -
1484 else if (d_ptr->refcount > 1) -
1485 d_ptr->detachPainterPrivate(this); -
1486 } QT_CATCH(...) { -
1487 // don't throw anything in the destructor. -
1488 } -
1489 if (d_ptr) { -
1490 // Make sure we haven't messed things up. -
1491 Q_ASSERT(d_ptr->inDestructor); -
1492 d_ptr->inDestructor = false; -
1493 Q_ASSERT(d_ptr->refcount == 1); -
1494 if (d_ptr->d_ptrs) -
1495 free(d_ptr->d_ptrs); -
1496 } -
1497} -
1498 -
1499/*! -
1500 Returns the paint device on which this painter is currently -
1501 painting, or 0 if the painter is not active. -
1502 -
1503 \sa isActive() -
1504*/ -
1505 -
1506QPaintDevice *QPainter::device() const -
1507{ -
1508 Q_D(const QPainter); -
1509 if (isActive() && d->engine->d_func()->currentClipDevice) -
1510 return d->engine->d_func()->currentClipDevice; -
1511 return d->original_device; -
1512} -
1513 -
1514/*! -
1515 Returns true if begin() has been called and end() has not yet been -
1516 called; otherwise returns false. -
1517 -
1518 \sa begin(), QPaintDevice::paintingActive() -
1519*/ -
1520 -
1521bool QPainter::isActive() const -
1522{ -
1523 Q_D(const QPainter); -
1524 return d->engine; -
1525} -
1526 -
1527/*! -
1528 Initializes the painters pen, background and font to the same as -
1529 the given \a device. -
1530 -
1531 \obsolete -
1532 -
1533 \sa begin(), {QPainter#Settings}{Settings} -
1534*/ -
1535void QPainter::initFrom(const QPaintDevice *device) -
1536{ -
1537 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0"); -
1538 Q_D(QPainter); -
1539 if (!d->engine) { -
1540 qWarning("QPainter::initFrom: Painter not active, aborted"); -
1541 return; -
1542 } -
1543 -
1544 device->initPainter(this); -
1545 -
1546 if (d->extended) { -
1547 d->extended->penChanged(); -
1548 } else if (d->engine) { -
1549 d->engine->setDirty(QPaintEngine::DirtyPen); -
1550 d->engine->setDirty(QPaintEngine::DirtyBrush); -
1551 d->engine->setDirty(QPaintEngine::DirtyFont); -
1552 } -
1553} -
1554 -
1555 -
1556/*! -
1557 Saves the current painter state (pushes the state onto a stack). A -
1558 save() must be followed by a corresponding restore(); the end() -
1559 function unwinds the stack. -
1560 -
1561 \sa restore() -
1562*/ -
1563 -
1564void QPainter::save() -
1565{ -
1566#ifdef QT_DEBUG_DRAW -
1567 if (qt_show_painter_debug_output) -
1568 printf("QPainter::save()\n"); -
1569#endif -
1570 Q_D(QPainter); -
1571 if (!d->engine) { -
1572 qWarning("QPainter::save: Painter not active"); -
1573 return; -
1574 } -
1575 -
1576 if (d->extended) { -
1577 d->state = d->extended->createState(d->states.back()); -
1578 d->extended->setState(d->state); -
1579 } else { -
1580 d->updateState(d->state); -
1581 d->state = new QPainterState(d->states.back()); -
1582 d->engine->state = d->state; -
1583 } -
1584 d->states.push_back(d->state); -
1585} -
1586 -
1587/*! -
1588 Restores the current painter state (pops a saved state off the -
1589 stack). -
1590 -
1591 \sa save() -
1592*/ -
1593 -
1594void QPainter::restore() -
1595{ -
1596#ifdef QT_DEBUG_DRAW -
1597 if (qt_show_painter_debug_output) -
1598 printf("QPainter::restore()\n"); -
1599#endif -
1600 Q_D(QPainter); -
1601 if (d->states.size()<=1) { -
1602 qWarning("QPainter::restore: Unbalanced save/restore"); -
1603 return; -
1604 } else if (!d->engine) { -
1605 qWarning("QPainter::restore: Painter not active"); -
1606 return; -
1607 } -
1608 -
1609 QPainterState *tmp = d->state; -
1610 d->states.pop_back(); -
1611 d->state = d->states.back(); -
1612 d->txinv = false; -
1613 -
1614 if (d->extended) { -
1615 d->checkEmulation(); -
1616 d->extended->setState(d->state); -
1617 delete tmp; -
1618 return; -
1619 } -
1620 -
1621 // trigger clip update if the clip path/region has changed since -
1622 // last save -
1623 if (!d->state->clipInfo.isEmpty() -
1624 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) { -
1625 // reuse the tmp state to avoid any extra allocs... -
1626 tmp->dirtyFlags = QPaintEngine::DirtyClipPath; -
1627 tmp->clipOperation = Qt::NoClip; -
1628 tmp->clipPath = QPainterPath(); -
1629 d->engine->updateState(*tmp); -
1630 // replay the list of clip states, -
1631 for (int i=0; i<d->state->clipInfo.size(); ++i) { -
1632 const QPainterClipInfo &info = d->state->clipInfo.at(i); -
1633 tmp->matrix = info.matrix; -
1634 tmp->matrix *= d->state->redirectionMatrix; -
1635 tmp->clipOperation = info.operation; -
1636 if (info.clipType == QPainterClipInfo::RectClip) { -
1637 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform; -
1638 tmp->clipRegion = info.rect; -
1639 } else if (info.clipType == QPainterClipInfo::RegionClip) { -
1640 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform; -
1641 tmp->clipRegion = info.region; -
1642 } else { // clipType == QPainterClipInfo::PathClip -
1643 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform; -
1644 tmp->clipPath = info.path; -
1645 } -
1646 d->engine->updateState(*tmp); -
1647 } -
1648 -
1649 -
1650 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed: -
1651 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion); -
1652 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion); -
1653 tmp->changeFlags |= QPaintEngine::DirtyTransform; -
1654 } -
1655 -
1656 d->updateState(d->state); -
1657 delete tmp; -
1658} -
1659 -
1660 -
1661/*! -
1662 -
1663 \fn bool QPainter::begin(QPaintDevice *device) -
1664 -
1665 Begins painting the paint \a device and returns true if -
1666 successful; otherwise returns false. -
1667 -
1668 Notice that all painter settings (setPen(), setBrush() etc.) are reset -
1669 to default values when begin() is called. -
1670 -
1671 The errors that can occur are serious problems, such as these: -
1672 -
1673 \snippet code/src_gui_painting_qpainter.cpp 3 -
1674 -
1675 Note that most of the time, you can use one of the constructors -
1676 instead of begin(), and that end() is automatically done at -
1677 destruction. -
1678 -
1679 \warning A paint device can only be painted by one painter at a -
1680 time. -
1681 -
1682 \warning Painting on a QImage with the format -
1683 QImage::Format_Indexed8 is not supported. -
1684 -
1685 \sa end(), QPainter() -
1686*/ -
1687 -
1688static inline void qt_cleanup_painter_state(QPainterPrivate *d) -
1689{ -
1690 d->states.clear(); -
1691 delete d->state; -
1692 d->state = 0; -
1693 d->engine = 0; -
1694 d->device = 0; -
1695} -
1696 -
1697bool QPainter::begin(QPaintDevice *pd) -
1698{ -
1699 Q_ASSERT(pd);
executed (the execution status of this line is deduced): qt_noop();
-
1700 -
1701 if (pd->painters > 0) {
evaluated: pd->painters > 0
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:28784
1-28784
1702 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
executed (the execution status of this line is deduced): QMessageLogger("painting/qpainter.cpp", 1702, __PRETTY_FUNCTION__).warning("QPainter::begin: A paint device can only be painted by one painter at a time.");
-
1703 return false;
executed: return false;
Execution Count:1
1
1704 } -
1705 -
1706 if (d_ptr->engine) {
evaluated: d_ptr->engine
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:28783
1-28783
1707 qWarning("QPainter::begin: Painter already active");
executed (the execution status of this line is deduced): QMessageLogger("painting/qpainter.cpp", 1707, __PRETTY_FUNCTION__).warning("QPainter::begin: Painter already active");
-
1708 return false;
executed: return false;
Execution Count:1
1
1709 } -
1710 -
1711 if (QPainterPrivate::attachPainterPrivate(this, pd))
evaluated: QPainterPrivate::attachPainterPrivate(this, pd)
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:28777
6-28777
1712 return true;
executed: return true;
Execution Count:6
6
1713 -
1714 Q_D(QPainter);
executed (the execution status of this line is deduced): QPainterPrivate * const d = d_func();
-
1715 -
1716 d->helper_device = pd;
executed (the execution status of this line is deduced): d->helper_device = pd;
-
1717 d->original_device = pd;
executed (the execution status of this line is deduced): d->original_device = pd;
-
1718 -
1719 QPoint redirectionOffset;
executed (the execution status of this line is deduced): QPoint redirectionOffset;
-
1720 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
executed (the execution status of this line is deduced): QPaintDevice *rpd = pd->redirected(&redirectionOffset);
-
1721 if (rpd)
evaluated: rpd
TRUEFALSE
yes
Evaluation Count:23420
yes
Evaluation Count:5357
5357-23420
1722 pd = rpd;
executed: pd = rpd;
Execution Count:23420
23420
1723 -
1724#ifdef QT_DEBUG_DRAW -
1725 if (qt_show_painter_debug_output) -
1726 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType()); -
1727#endif -
1728 -
1729 if (pd->devType() == QInternal::Pixmap)
evaluated: pd->devType() == QInternal::Pixmap
TRUEFALSE
yes
Evaluation Count:834
yes
Evaluation Count:27943
834-27943
1730 static_cast<QPixmap *>(pd)->detach();
executed: static_cast<QPixmap *>(pd)->detach();
Execution Count:834
834
1731 else if (pd->devType() == QInternal::Image)
evaluated: pd->devType() == QInternal::Image
TRUEFALSE
yes
Evaluation Count:27905
yes
Evaluation Count:38
38-27905
1732 static_cast<QImage *>(pd)->detach();
executed: static_cast<QImage *>(pd)->detach();
Execution Count:27905
27905
1733 -
1734 d->engine = pd->paintEngine();
executed (the execution status of this line is deduced): d->engine = pd->paintEngine();
-
1735 -
1736 if (!d->engine) {
evaluated: !d->engine
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:28774
2-28774
1737 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
executed (the execution status of this line is deduced): QMessageLogger("painting/qpainter.cpp", 1737, __PRETTY_FUNCTION__).warning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
-
1738 return false;
executed: return false;
Execution Count:2
2
1739 } -
1740 -
1741 d->device = pd;
executed (the execution status of this line is deduced): d->device = pd;
-
1742 -
1743 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
evaluated: d->engine->isExtended()
TRUEFALSE
yes
Evaluation Count:28736
yes
Evaluation Count:38
38-28736
1744 if (d->emulationEngine)
partially evaluated: d->emulationEngine
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:28774
0-28774
1745 d->emulationEngine->real_engine = d->extended;
never executed: d->emulationEngine->real_engine = d->extended;
0
1746 -
1747 // Setup new state... -
1748 Q_ASSERT(!d->state);
executed (the execution status of this line is deduced): qt_noop();
-
1749 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
evaluated: d->extended
TRUEFALSE
yes
Evaluation Count:28736
yes
Evaluation Count:38
38-28736
1750 d->state->painter = this;
executed (the execution status of this line is deduced): d->state->painter = this;
-
1751 d->states.push_back(d->state);
executed (the execution status of this line is deduced): d->states.push_back(d->state);
-
1752 -
1753 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
executed (the execution status of this line is deduced): d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
-
1754 d->state->brushOrigin = QPointF();
executed (the execution status of this line is deduced): d->state->brushOrigin = QPointF();
-
1755 -
1756 // Slip a painter state into the engine before we do any other operations -
1757 if (d->extended)
evaluated: d->extended
TRUEFALSE
yes
Evaluation Count:28737
yes
Evaluation Count:38
38-28737
1758 d->extended->setState(d->state);
executed: d->extended->setState(d->state);
Execution Count:28737
28737
1759 else -
1760 d->engine->state = d->state;
executed: d->engine->state = d->state;
Execution Count:38
38
1761 -
1762 switch (pd->devType()) { -
1763 case QInternal::Pixmap: -
1764 { -
1765 QPixmap *pm = static_cast<QPixmap *>(pd);
executed (the execution status of this line is deduced): QPixmap *pm = static_cast<QPixmap *>(pd);
-
1766 Q_ASSERT(pm);
executed (the execution status of this line is deduced): qt_noop();
-
1767 if (pm->isNull()) {
partially evaluated: pm->isNull()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:833
0-833
1768 qWarning("QPainter::begin: Cannot paint on a null pixmap");
never executed (the execution status of this line is deduced): QMessageLogger("painting/qpainter.cpp", 1768, __PRETTY_FUNCTION__).warning("QPainter::begin: Cannot paint on a null pixmap");
-
1769 qt_cleanup_painter_state(d);
never executed (the execution status of this line is deduced): qt_cleanup_painter_state(d);
-
1770 return false;
never executed: return false;
0
1771 } -
1772 -
1773 if (pm->depth() == 1) {
evaluated: pm->depth() == 1
TRUEFALSE
yes
Evaluation Count:5
yes
Evaluation Count:828
5-828
1774 d->state->pen = QPen(Qt::color1);
executed (the execution status of this line is deduced): d->state->pen = QPen(Qt::color1);
-
1775 d->state->brush = QBrush(Qt::color0);
executed (the execution status of this line is deduced): d->state->brush = QBrush(Qt::color0);
-
1776 }
executed: }
Execution Count:5
5
1777 break;
executed: break;
Execution Count:833
833
1778 } -
1779 case QInternal::Image: -
1780 { -
1781 QImage *img = static_cast<QImage *>(pd);
executed (the execution status of this line is deduced): QImage *img = static_cast<QImage *>(pd);
-
1782 Q_ASSERT(img);
executed (the execution status of this line is deduced): qt_noop();
-
1783 if (img->isNull()) {
partially evaluated: img->isNull()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:27904
0-27904
1784 qWarning("QPainter::begin: Cannot paint on a null image");
never executed (the execution status of this line is deduced): QMessageLogger("painting/qpainter.cpp", 1784, __PRETTY_FUNCTION__).warning("QPainter::begin: Cannot paint on a null image");
-
1785 qt_cleanup_painter_state(d);
never executed (the execution status of this line is deduced): qt_cleanup_painter_state(d);
-
1786 return false;
never executed: return false;
0
1787 } else if (img->format() == QImage::Format_Indexed8) {
evaluated: img->format() == QImage::Format_Indexed8
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:27903
1-27903
1788 // Painting on indexed8 images is not supported. -
1789 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
executed (the execution status of this line is deduced): QMessageLogger("painting/qpainter.cpp", 1789, __PRETTY_FUNCTION__).warning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
-
1790 qt_cleanup_painter_state(d);
executed (the execution status of this line is deduced): qt_cleanup_painter_state(d);
-
1791 return false;
executed: return false;
Execution Count:1
1
1792 } -
1793 if (img->depth() == 1) {
evaluated: img->depth() == 1
TRUEFALSE
yes
Evaluation Count:162
yes
Evaluation Count:27741
162-27741
1794 d->state->pen = QPen(Qt::color1);
executed (the execution status of this line is deduced): d->state->pen = QPen(Qt::color1);
-
1795 d->state->brush = QBrush(Qt::color0);
executed (the execution status of this line is deduced): d->state->brush = QBrush(Qt::color0);
-
1796 }
executed: }
Execution Count:162
162
1797 break;
executed: break;
Execution Count:27903
27903
1798 } -
1799 default: -
1800 break;
executed: break;
Execution Count:38
38
1801 } -
1802 if (d->state->ww == 0) // For compat with 3.x painter defaults
partially evaluated: d->state->ww == 0
TRUEFALSE
yes
Evaluation Count:28774
no
Evaluation Count:0
0-28774
1803 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
executed: d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
Execution Count:28774
28774
1804 -
1805 d->engine->setPaintDevice(pd);
executed (the execution status of this line is deduced): d->engine->setPaintDevice(pd);
-
1806 -
1807 bool begun = d->engine->begin(pd);
executed (the execution status of this line is deduced): bool begun = d->engine->begin(pd);
-
1808 if (!begun) {
evaluated: !begun
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:28773
1-28773
1809 qWarning("QPainter::begin(): Returned false");
executed (the execution status of this line is deduced): QMessageLogger("painting/qpainter.cpp", 1809, __PRETTY_FUNCTION__).warning("QPainter::begin(): Returned false");
-
1810 if (d->engine->isActive()) {
partially evaluated: d->engine->isActive()
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1
0-1
1811 end();
never executed (the execution status of this line is deduced): end();
-
1812 } else {
never executed: }
0
1813 qt_cleanup_painter_state(d);
executed (the execution status of this line is deduced): qt_cleanup_painter_state(d);
-
1814 }
executed: }
Execution Count:1
1
1815 return false;
executed: return false;
Execution Count:1
1
1816 } else { -
1817 d->engine->setActive(begun);
executed (the execution status of this line is deduced): d->engine->setActive(begun);
-
1818 }
executed: }
Execution Count:28773
28773
1819 -
1820 // Copy painter properties from original paint device, -
1821 // required for QPixmap::grabWidget() -
1822 if (d->original_device->devType() == QInternal::Widget) {
evaluated: d->original_device->devType() == QInternal::Widget
TRUEFALSE
yes
Evaluation Count:23420
yes
Evaluation Count:5353
5353-23420
1823 initFrom(d->original_device);
executed (the execution status of this line is deduced): initFrom(d->original_device);
-
1824 } else {
executed: }
Execution Count:23420
23420
1825 d->state->layoutDirection = Qt::LayoutDirectionAuto;
executed (the execution status of this line is deduced): d->state->layoutDirection = Qt::LayoutDirectionAuto;
-
1826 // make sure we have a font compatible with the paintdevice -
1827 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
executed (the execution status of this line is deduced): d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
-
1828 }
executed: }
Execution Count:5353
5353
1829 -
1830 QRect systemRect = d->engine->systemRect();
executed (the execution status of this line is deduced): QRect systemRect = d->engine->systemRect();
-
1831 if (!systemRect.isEmpty()) {
evaluated: !systemRect.isEmpty()
TRUEFALSE
yes
Evaluation Count:23420
yes
Evaluation Count:5353
5353-23420
1832 d->state->ww = d->state->vw = systemRect.width();
executed (the execution status of this line is deduced): d->state->ww = d->state->vw = systemRect.width();
-
1833 d->state->wh = d->state->vh = systemRect.height();
executed (the execution status of this line is deduced): d->state->wh = d->state->vh = systemRect.height();
-
1834 } else {
executed: }
Execution Count:23420
23420
1835 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
executed (the execution status of this line is deduced): d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
-
1836 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
executed (the execution status of this line is deduced): d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
-
1837 }
executed: }
Execution Count:5353
5353
1838 -
1839 const QPoint coordinateOffset = d->engine->coordinateOffset();
executed (the execution status of this line is deduced): const QPoint coordinateOffset = d->engine->coordinateOffset();
-
1840 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
executed (the execution status of this line is deduced): d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
-
1841 -
1842 Q_ASSERT(d->engine->isActive());
executed (the execution status of this line is deduced): qt_noop();
-
1843 -
1844#ifdef Q_OS_MAC -
1845 // Limited feature introduction for Qt 5.0.0, remove ifdef in a later release. -
1846 const bool isHighDpi = (pd->devType() == QInternal::Printer || d->device->physicalDpiX() == 0 || d->device->logicalDpiX() == 0) ? -
1847 false : (d->device->physicalDpiX() / d->device->logicalDpiX() > 1); -
1848#else -
1849 const bool isHighDpi = false;
executed (the execution status of this line is deduced): const bool isHighDpi = false;
-
1850#endif -
1851 if (!d->state->redirectionMatrix.isIdentity() || isHighDpi)
evaluated: !d->state->redirectionMatrix.isIdentity()
TRUEFALSE
yes
Evaluation Count:15494
yes
Evaluation Count:13279
partially evaluated: isHighDpi
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:13279
0-15494
1852 d->updateMatrix();
executed: d->updateMatrix();
Execution Count:15494
15494
1853 -
1854 Q_ASSERT(d->engine->isActive());
executed (the execution status of this line is deduced): qt_noop();
-
1855 d->state->renderHints = QPainter::TextAntialiasing;
executed (the execution status of this line is deduced): d->state->renderHints = QPainter::TextAntialiasing;
-
1856 ++d->device->painters;
executed (the execution status of this line is deduced): ++d->device->painters;
-
1857 -
1858 d->state->emulationSpecifier = 0;
executed (the execution status of this line is deduced): d->state->emulationSpecifier = 0;
-
1859 -
1860 return true;
executed: return true;
Execution Count:28773
28773
1861} -
1862 -
1863/*! -
1864 Ends painting. Any resources used while painting are released. You -
1865 don't normally need to call this since it is called by the -
1866 destructor. -
1867 -
1868 Returns true if the painter is no longer active; otherwise returns false. -
1869 -
1870 \sa begin(), isActive() -
1871*/ -
1872 -
1873bool QPainter::end() -
1874{ -
1875#ifdef QT_DEBUG_DRAW -
1876 if (qt_show_painter_debug_output) -
1877 printf("QPainter::end()\n"); -
1878#endif -
1879 Q_D(QPainter); -
1880 -
1881 if (!d->engine) { -
1882 qWarning("QPainter::end: Painter not active, aborted"); -
1883 qt_cleanup_painter_state(d); -
1884 return false; -
1885 } -
1886 -
1887 if (d->refcount > 1) { -
1888 d->detachPainterPrivate(this); -
1889 return true; -
1890 } -
1891 -
1892 bool ended = true; -
1893 -
1894 if (d->engine->isActive()) { -
1895 ended = d->engine->end(); -
1896 d->updateState(0); -
1897 -
1898 --d->device->painters; -
1899 if (d->device->painters == 0) { -
1900 d->engine->setPaintDevice(0); -
1901 d->engine->setActive(false); -
1902 } -
1903 } -
1904 -
1905 if (d->states.size() > 1) { -
1906 qWarning("QPainter::end: Painter ended with %d saved states", -
1907 d->states.size()); -
1908 } -
1909 -
1910 if (d->engine->autoDestruct()) { -
1911 delete d->engine; -
1912 } -
1913 -
1914 if (d->emulationEngine) { -
1915 delete d->emulationEngine; -
1916 d->emulationEngine = 0; -
1917 } -
1918 -
1919 if (d->extended) { -
1920 d->extended = 0; -
1921 } -
1922 -
1923 qt_cleanup_painter_state(d); -
1924 -
1925 return ended; -
1926} -
1927 -
1928 -
1929/*! -
1930 Returns the paint engine that the painter is currently operating -
1931 on if the painter is active; otherwise 0. -
1932 -
1933 \sa isActive() -
1934*/ -
1935QPaintEngine *QPainter::paintEngine() const -
1936{ -
1937 Q_D(const QPainter); -
1938 return d->engine; -
1939} -
1940 -
1941/*! -
1942 \since 4.6 -
1943 -
1944 Flushes the painting pipeline and prepares for the user issuing commands -
1945 directly to the underlying graphics context. Must be followed by a call to -
1946 endNativePainting(). -
1947 -
1948 Note that only the states the underlying paint engine changes will be reset -
1949 to their respective default states. The states we reset may change from -
1950 release to release. The following states are currently reset in the OpenGL -
1951 2 engine: -
1952 -
1953 \list -
1954 \li blending is disabled -
1955 \li the depth, stencil and scissor tests are disabled -
1956 \li the active texture unit is reset to 0 -
1957 \li the depth mask, depth function and the clear depth are reset to their -
1958 default values -
1959 \li the stencil mask, stencil operation and stencil function are reset to -
1960 their default values -
1961 \li the current color is reset to solid white -
1962 \endlist -
1963 -
1964 If, for example, the OpenGL polygon mode is changed by the user inside a -
1965 beginNativePaint()/endNativePainting() block, it will not be reset to the -
1966 default state by endNativePainting(). Here is an example that shows -
1967 intermixing of painter commands and raw OpenGL commands: -
1968 -
1969 \snippet code/src_gui_painting_qpainter.cpp 21 -
1970 -
1971 \sa endNativePainting() -
1972*/ -
1973void QPainter::beginNativePainting() -
1974{ -
1975 Q_D(QPainter); -
1976 if (!d->engine) { -
1977 qWarning("QPainter::beginNativePainting: Painter not active"); -
1978 return; -
1979 } -
1980 -
1981 if (d->extended) -
1982 d->extended->beginNativePainting(); -
1983} -
1984 -
1985/*! -
1986 \since 4.6 -
1987 -
1988 Restores the painter after manually issuing native painting commands. Lets -
1989 the painter restore any native state that it relies on before calling any -
1990 other painter commands. -
1991 -
1992 \sa beginNativePainting() -
1993*/ -
1994void QPainter::endNativePainting() -
1995{ -
1996 Q_D(const QPainter); -
1997 if (!d->engine) { -
1998 qWarning("QPainter::beginNativePainting: Painter not active"); -
1999 return; -
2000 } -
2001 -
2002 if (d->extended) -
2003 d->extended->endNativePainting(); -
2004 else -
2005 d->engine->syncState(); -
2006} -
2007 -
2008/*! -
2009 Returns the font metrics for the painter if the painter is -
2010 active. Otherwise, the return value is undefined. -
2011 -
2012 \sa font(), isActive(), {QPainter#Settings}{Settings} -
2013*/ -
2014 -
2015QFontMetrics QPainter::fontMetrics() const -
2016{ -
2017 Q_D(const QPainter); -
2018 if (!d->engine) { -
2019 qWarning("QPainter::fontMetrics: Painter not active"); -
2020 return QFontMetrics(QFont()); -
2021 } -
2022 return QFontMetrics(d->state->font); -
2023} -
2024 -
2025 -
2026/*! -
2027 Returns the font info for the painter if the painter is -
2028 active. Otherwise, the return value is undefined. -
2029 -
2030 \sa font(), isActive(), {QPainter#Settings}{Settings} -
2031*/ -
2032 -
2033QFontInfo QPainter::fontInfo() const -
2034{ -
2035 Q_D(const QPainter); -
2036 if (!d->engine) { -
2037 qWarning("QPainter::fontInfo: Painter not active"); -
2038 return QFontInfo(QFont()); -
2039 } -
2040 return QFontInfo(d->state->font); -
2041} -
2042 -
2043/*! -
2044 \since 4.2 -
2045 -
2046 Returns the opacity of the painter. The default value is -
2047 1. -
2048*/ -
2049 -
2050qreal QPainter::opacity() const -
2051{ -
2052 Q_D(const QPainter); -
2053 if (!d->engine) { -
2054 qWarning("QPainter::opacity: Painter not active"); -
2055 return 1.0; -
2056 } -
2057 return d->state->opacity; -
2058} -
2059 -
2060/*! -
2061 \since 4.2 -
2062 -
2063 Sets the opacity of the painter to \a opacity. The value should -
2064 be in the range 0.0 to 1.0, where 0.0 is fully transparent and -
2065 1.0 is fully opaque. -
2066 -
2067 Opacity set on the painter will apply to all drawing operations -
2068 individually. -
2069*/ -
2070 -
2071void QPainter::setOpacity(qreal opacity) -
2072{ -
2073 Q_D(QPainter); -
2074 -
2075 if (!d->engine) { -
2076 qWarning("QPainter::setOpacity: Painter not active"); -
2077 return; -
2078 } -
2079 -
2080 opacity = qMin(qreal(1), qMax(qreal(0), opacity)); -
2081 -
2082 if (opacity == d->state->opacity) -
2083 return; -
2084 -
2085 d->state->opacity = opacity; -
2086 -
2087 if (d->extended) -
2088 d->extended->opacityChanged(); -
2089 else -
2090 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity; -
2091} -
2092 -
2093 -
2094/*! -
2095 Returns the currently set brush origin. -
2096 -
2097 \sa setBrushOrigin(), {QPainter#Settings}{Settings} -
2098*/ -
2099 -
2100QPoint QPainter::brushOrigin() const -
2101{ -
2102 Q_D(const QPainter); -
2103 if (!d->engine) { -
2104 qWarning("QPainter::brushOrigin: Painter not active"); -
2105 return QPoint(); -
2106 } -
2107 return QPointF(d->state->brushOrigin).toPoint(); -
2108} -
2109 -
2110/*! -
2111 \fn void QPainter::setBrushOrigin(const QPointF &position) -
2112 -
2113 Sets the brush origin to \a position. -
2114 -
2115 The brush origin specifies the (0, 0) coordinate of the painter's -
2116 brush. -
2117 -
2118 Note that while the brushOrigin() was necessary to adopt the -
2119 parent's background for a widget in Qt 3, this is no longer the -
2120 case since the Qt 4 painter doesn't paint the background unless -
2121 you explicitly tell it to do so by setting the widget's \l -
2122 {QWidget::autoFillBackground}{autoFillBackground} property to -
2123 true. -
2124 -
2125 \sa brushOrigin(), {QPainter#Settings}{Settings} -
2126*/ -
2127 -
2128void QPainter::setBrushOrigin(const QPointF &p) -
2129{ -
2130 Q_D(QPainter); -
2131#ifdef QT_DEBUG_DRAW -
2132 if (qt_show_painter_debug_output) -
2133 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y()); -
2134#endif -
2135 -
2136 if (!d->engine) { -
2137 qWarning("QPainter::setBrushOrigin: Painter not active"); -
2138 return; -
2139 } -
2140 -
2141 d->state->brushOrigin = p; -
2142 -
2143 if (d->extended) { -
2144 d->extended->brushOriginChanged(); -
2145 return; -
2146 } -
2147 -
2148 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin; -
2149} -
2150 -
2151/*! -
2152 \fn void QPainter::setBrushOrigin(const QPoint &position) -
2153 \overload -
2154 -
2155 Sets the brush's origin to the given \a position. -
2156*/ -
2157 -
2158/*! -
2159 \fn void QPainter::setBrushOrigin(int x, int y) -
2160 -
2161 \overload -
2162 -
2163 Sets the brush's origin to point (\a x, \a y). -
2164*/ -
2165 -
2166/*! -
2167 \enum QPainter::CompositionMode -
2168 -
2169 Defines the modes supported for digital image compositing. -
2170 Composition modes are used to specify how the pixels in one image, -
2171 the source, are merged with the pixel in another image, the -
2172 destination. -
2173 -
2174 Please note that the bitwise raster operation modes, denoted with -
2175 a RasterOp prefix, are only natively supported in the X11 and -
2176 raster paint engines. This means that the only way to utilize -
2177 these modes on the Mac is via a QImage. The RasterOp denoted blend -
2178 modes are \e not supported for pens and brushes with alpha -
2179 components. Also, turning on the QPainter::Antialiasing render -
2180 hint will effectively disable the RasterOp modes. -
2181 -
2182 -
2183 \image qpainter-compositionmode1.png -
2184 \image qpainter-compositionmode2.png -
2185 -
2186 The most common type is SourceOver (often referred to as just -
2187 alpha blending) where the source pixel is blended on top of the -
2188 destination pixel in such a way that the alpha component of the -
2189 source defines the translucency of the pixel. -
2190 -
2191 When the paint device is a QImage, the image format must be set to -
2192 \l {QImage::Format}{Format_ARGB32_Premultiplied} or -
2193 \l {QImage::Format}{Format_ARGB32} for the composition modes to have -
2194 any effect. For performance the premultiplied version is the preferred -
2195 format. -
2196 -
2197 When a composition mode is set it applies to all painting -
2198 operator, pens, brushes, gradients and pixmap/image drawing. -
2199 -
2200 \value CompositionMode_SourceOver This is the default mode. The -
2201 alpha of the source is used to blend the pixel on top of the -
2202 destination. -
2203 -
2204 \value CompositionMode_DestinationOver The alpha of the -
2205 destination is used to blend it on top of the source pixels. This -
2206 mode is the inverse of CompositionMode_SourceOver. -
2207 -
2208 \value CompositionMode_Clear The pixels in the destination are -
2209 cleared (set to fully transparent) independent of the source. -
2210 -
2211 \value CompositionMode_Source The output is the source -
2212 pixel. (This means a basic copy operation and is identical to -
2213 SourceOver when the source pixel is opaque). -
2214 -
2215 \value CompositionMode_Destination The output is the destination -
2216 pixel. This means that the blending has no effect. This mode is -
2217 the inverse of CompositionMode_Source. -
2218 -
2219 \value CompositionMode_SourceIn The output is the source, where -
2220 the alpha is reduced by that of the destination. -
2221 -
2222 \value CompositionMode_DestinationIn The output is the -
2223 destination, where the alpha is reduced by that of the -
2224 source. This mode is the inverse of CompositionMode_SourceIn. -
2225 -
2226 \value CompositionMode_SourceOut The output is the source, where -
2227 the alpha is reduced by the inverse of destination. -
2228 -
2229 \value CompositionMode_DestinationOut The output is the -
2230 destination, where the alpha is reduced by the inverse of the -
2231 source. This mode is the inverse of CompositionMode_SourceOut. -
2232 -
2233 \value CompositionMode_SourceAtop The source pixel is blended on -
2234 top of the destination, with the alpha of the source pixel reduced -
2235 by the alpha of the destination pixel. -
2236 -
2237 \value CompositionMode_DestinationAtop The destination pixel is -
2238 blended on top of the source, with the alpha of the destination -
2239 pixel is reduced by the alpha of the destination pixel. This mode -
2240 is the inverse of CompositionMode_SourceAtop. -
2241 -
2242 \value CompositionMode_Xor The source, whose alpha is reduced with -
2243 the inverse of the destination alpha, is merged with the -
2244 destination, whose alpha is reduced by the inverse of the source -
2245 alpha. CompositionMode_Xor is not the same as the bitwise Xor. -
2246 -
2247 \value CompositionMode_Plus Both the alpha and color of the source -
2248 and destination pixels are added together. -
2249 -
2250 \value CompositionMode_Multiply The output is the source color -
2251 multiplied by the destination. Multiplying a color with white -
2252 leaves the color unchanged, while multiplying a color -
2253 with black produces black. -
2254 -
2255 \value CompositionMode_Screen The source and destination colors -
2256 are inverted and then multiplied. Screening a color with white -
2257 produces white, whereas screening a color with black leaves the -
2258 color unchanged. -
2259 -
2260 \value CompositionMode_Overlay Multiplies or screens the colors -
2261 depending on the destination color. The destination color is mixed -
2262 with the source color to reflect the lightness or darkness of the -
2263 destination. -
2264 -
2265 \value CompositionMode_Darken The darker of the source and -
2266 destination colors is selected. -
2267 -
2268 \value CompositionMode_Lighten The lighter of the source and -
2269 destination colors is selected. -
2270 -
2271 \value CompositionMode_ColorDodge The destination color is -
2272 brightened to reflect the source color. A black source color -
2273 leaves the destination color unchanged. -
2274 -
2275 \value CompositionMode_ColorBurn The destination color is darkened -
2276 to reflect the source color. A white source color leaves the -
2277 destination color unchanged. -
2278 -
2279 \value CompositionMode_HardLight Multiplies or screens the colors -
2280 depending on the source color. A light source color will lighten -
2281 the destination color, whereas a dark source color will darken the -
2282 destination color. -
2283 -
2284 \value CompositionMode_SoftLight Darkens or lightens the colors -
2285 depending on the source color. Similar to -
2286 CompositionMode_HardLight. -
2287 -
2288 \value CompositionMode_Difference Subtracts the darker of the -
2289 colors from the lighter. Painting with white inverts the -
2290 destination color, whereas painting with black leaves the -
2291 destination color unchanged. -
2292 -
2293 \value CompositionMode_Exclusion Similar to -
2294 CompositionMode_Difference, but with a lower contrast. Painting -
2295 with white inverts the destination color, whereas painting with -
2296 black leaves the destination color unchanged. -
2297 -
2298 \value RasterOp_SourceOrDestination Does a bitwise OR operation on -
2299 the source and destination pixels (src OR dst). -
2300 -
2301 \value RasterOp_SourceAndDestination Does a bitwise AND operation -
2302 on the source and destination pixels (src AND dst). -
2303 -
2304 \value RasterOp_SourceXorDestination Does a bitwise XOR operation -
2305 on the source and destination pixels (src XOR dst). -
2306 -
2307 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR -
2308 operation on the source and destination pixels ((NOT src) AND (NOT -
2309 dst)). -
2310 -
2311 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND -
2312 operation on the source and destination pixels ((NOT src) OR (NOT -
2313 dst)). -
2314 -
2315 \value RasterOp_NotSourceXorDestination Does a bitwise operation -
2316 where the source pixels are inverted and then XOR'ed with the -
2317 destination ((NOT src) XOR dst). -
2318 -
2319 \value RasterOp_NotSource Does a bitwise operation where the -
2320 source pixels are inverted (NOT src). -
2321 -
2322 \value RasterOp_NotSourceAndDestination Does a bitwise operation -
2323 where the source is inverted and then AND'ed with the destination -
2324 ((NOT src) AND dst). -
2325 -
2326 \value RasterOp_SourceAndNotDestination Does a bitwise operation -
2327 where the source is AND'ed with the inverted destination pixels -
2328 (src AND (NOT dst)). -
2329 -
2330 \value RasterOp_NotSourceOrDestination Does a bitwise operation -
2331 where the source is inverted and then OR'ed with the destination -
2332 ((NOT src) OR dst). -
2333 -
2334 \value RasterOp_ClearDestination The pixels in the destination are -
2335 cleared (set to 0) independent of the source. -
2336 -
2337 \value RasterOp_SetDestination The pixels in the destination are -
2338 set (set to 1) independent of the source. -
2339 -
2340 \value RasterOp_NotDestination Does a bitwise operation -
2341 where the destination pixels are inverted (NOT dst). -
2342 -
2343 \value RasterOp_SourceOrNotDestination Does a bitwise operation -
2344 where the source is OR'ed with the inverted destination pixels -
2345 (src OR (NOT dst)). -
2346 -
2347 \sa compositionMode(), setCompositionMode(), {QPainter#Composition -
2348 Modes}{Composition Modes}, {Image Composition Example} -
2349*/ -
2350 -
2351/*! -
2352 Sets the composition mode to the given \a mode. -
2353 -
2354 \warning Only a QPainter operating on a QImage fully supports all -
2355 composition modes. The RasterOp modes are supported for X11 as -
2356 described in compositionMode(). -
2357 -
2358 \sa compositionMode() -
2359*/ -
2360void QPainter::setCompositionMode(CompositionMode mode) -
2361{ -
2362 Q_D(QPainter); -
2363 if (!d->engine) { -
2364 qWarning("QPainter::setCompositionMode: Painter not active"); -
2365 return; -
2366 } -
2367 if (d->state->composition_mode == mode) -
2368 return; -
2369 if (d->extended) { -
2370 d->state->composition_mode = mode; -
2371 d->extended->compositionModeChanged(); -
2372 return; -
2373 } -
2374 -
2375 if (mode >= QPainter::RasterOp_SourceOrDestination) { -
2376 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) { -
2377 qWarning("QPainter::setCompositionMode: " -
2378 "Raster operation modes not supported on device"); -
2379 return; -
2380 } -
2381 } else if (mode >= QPainter::CompositionMode_Plus) { -
2382 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) { -
2383 qWarning("QPainter::setCompositionMode: " -
2384 "Blend modes not supported on device"); -
2385 return; -
2386 } -
2387 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) { -
2388 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) { -
2389 qWarning("QPainter::setCompositionMode: " -
2390 "PorterDuff modes not supported on device"); -
2391 return; -
2392 } -
2393 } -
2394 -
2395 d->state->composition_mode = mode; -
2396 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode; -
2397} -
2398 -
2399/*! -
2400 Returns the current composition mode. -
2401 -
2402 \sa CompositionMode, setCompositionMode() -
2403*/ -
2404QPainter::CompositionMode QPainter::compositionMode() const -
2405{ -
2406 Q_D(const QPainter); -
2407 if (!d->engine) { -
2408 qWarning("QPainter::compositionMode: Painter not active"); -
2409 return QPainter::CompositionMode_SourceOver; -
2410 } -
2411 return d->state->composition_mode; -
2412} -
2413 -
2414/*! -
2415 Returns the current background brush. -
2416 -
2417 \sa setBackground(), {QPainter#Settings}{Settings} -
2418*/ -
2419 -
2420const QBrush &QPainter::background() const -
2421{ -
2422 Q_D(const QPainter); -
2423 if (!d->engine) { -
2424 qWarning("QPainter::background: Painter not active"); -
2425 return d->fakeState()->brush; -
2426 } -
2427 return d->state->bgBrush; -
2428} -
2429 -
2430 -
2431/*! -
2432 Returns true if clipping has been set; otherwise returns false. -
2433 -
2434 \sa setClipping(), {QPainter#Clipping}{Clipping} -
2435*/ -
2436 -
2437bool QPainter::hasClipping() const -
2438{ -
2439 Q_D(const QPainter); -
2440 if (!d->engine) { -
2441 qWarning("QPainter::hasClipping: Painter not active"); -
2442 return false; -
2443 } -
2444 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip; -
2445} -
2446 -
2447 -
2448/*! -
2449 Enables clipping if \a enable is true, or disables clipping if \a -
2450 enable is false. -
2451 -
2452 \sa hasClipping(), {QPainter#Clipping}{Clipping} -
2453*/ -
2454 -
2455void QPainter::setClipping(bool enable) -
2456{ -
2457 Q_D(QPainter); -
2458#ifdef QT_DEBUG_DRAW -
2459 if (qt_show_painter_debug_output) -
2460 printf("QPainter::setClipping(), enable=%s, was=%s\n", -
2461 enable ? "on" : "off", -
2462 hasClipping() ? "on" : "off"); -
2463#endif -
2464 if (!d->engine) { -
2465 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin"); -
2466 return; -
2467 } -
2468 -
2469 if (hasClipping() == enable) -
2470 return; -
2471 -
2472 // we can't enable clipping if we don't have a clip -
2473 if (enable -
2474 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip)) -
2475 return; -
2476 d->state->clipEnabled = enable; -
2477 -
2478 if (d->extended) { -
2479 d->extended->clipEnabledChanged(); -
2480 return; -
2481 } -
2482 -
2483 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled; -
2484 d->updateState(d->state); -
2485} -
2486 -
2487 -
2488/*! -
2489 Returns the currently set clip region. Note that the clip region -
2490 is given in logical coordinates. -
2491 -
2492 \warning QPainter does not store the combined clip explicitly as -
2493 this is handled by the underlying QPaintEngine, so the path is -
2494 recreated on demand and transformed to the current logical -
2495 coordinate system. This is potentially an expensive operation. -
2496 -
2497 \sa setClipRegion(), clipPath(), setClipping() -
2498*/ -
2499 -
2500QRegion QPainter::clipRegion() const -
2501{ -
2502 Q_D(const QPainter); -
2503 if (!d->engine) { -
2504 qWarning("QPainter::clipRegion: Painter not active"); -
2505 return QRegion(); -
2506 } -
2507 -
2508 QRegion region; -
2509 bool lastWasNothing = true; -
2510 -
2511 if (!d->txinv) -
2512 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix(); -
2513 -
2514 // ### Falcon: Use QPainterPath -
2515 for (int i=0; i<d->state->clipInfo.size(); ++i) { -
2516 const QPainterClipInfo &info = d->state->clipInfo.at(i); -
2517 switch (info.clipType) { -
2518 -
2519 case QPainterClipInfo::RegionClip: { -
2520 QTransform matrix = (info.matrix * d->invMatrix); -
2521 if (lastWasNothing) { -
2522 region = info.region * matrix; -
2523 lastWasNothing = false; -
2524 continue; -
2525 } -
2526 if (info.operation == Qt::IntersectClip) -
2527 region &= info.region * matrix; -
2528 else if (info.operation == Qt::NoClip) { -
2529 lastWasNothing = true; -
2530 region = QRegion(); -
2531 } else -
2532 region = info.region * matrix; -
2533 break; -
2534 } -
2535 -
2536 case QPainterClipInfo::PathClip: { -
2537 QTransform matrix = (info.matrix * d->invMatrix); -
2538 if (lastWasNothing) { -
2539 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(), -
2540 info.path.fillRule()); -
2541 lastWasNothing = false; -
2542 continue; -
2543 } -
2544 if (info.operation == Qt::IntersectClip) { -
2545 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(), -
2546 info.path.fillRule()); -
2547 } else if (info.operation == Qt::NoClip) { -
2548 lastWasNothing = true; -
2549 region = QRegion(); -
2550 } else { -
2551 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(), -
2552 info.path.fillRule()); -
2553 } -
2554 break; -
2555 } -
2556 -
2557 case QPainterClipInfo::RectClip: { -
2558 QTransform matrix = (info.matrix * d->invMatrix); -
2559 if (lastWasNothing) { -
2560 region = QRegion(info.rect) * matrix; -
2561 lastWasNothing = false; -
2562 continue; -
2563 } -
2564 if (info.operation == Qt::IntersectClip) { -
2565 // Use rect intersection if possible. -
2566 if (matrix.type() <= QTransform::TxScale) -
2567 region &= matrix.mapRect(info.rect); -
2568 else -
2569 region &= matrix.map(QRegion(info.rect)); -
2570 } else if (info.operation == Qt::NoClip) { -
2571 lastWasNothing = true; -
2572 region = QRegion(); -
2573 } else { -
2574 region = QRegion(info.rect) * matrix; -
2575 } -
2576 break; -
2577 } -
2578 -
2579 case QPainterClipInfo::RectFClip: { -
2580 QTransform matrix = (info.matrix * d->invMatrix); -
2581 if (lastWasNothing) { -
2582 region = QRegion(info.rectf.toRect()) * matrix; -
2583 lastWasNothing = false; -
2584 continue; -
2585 } -
2586 if (info.operation == Qt::IntersectClip) { -
2587 // Use rect intersection if possible. -
2588 if (matrix.type() <= QTransform::TxScale) -
2589 region &= matrix.mapRect(info.rectf.toRect()); -
2590 else -
2591 region &= matrix.map(QRegion(info.rectf.toRect())); -
2592 } else if (info.operation == Qt::NoClip) { -
2593 lastWasNothing = true; -
2594 region = QRegion(); -
2595 } else { -
2596 region = QRegion(info.rectf.toRect()) * matrix; -
2597 } -
2598 break; -
2599 } -
2600 } -
2601 } -
2602 -
2603 return region; -
2604} -
2605 -
2606extern QPainterPath qt_regionToPath(const QRegion &region); -
2607 -
2608/*! -
2609 Returns the currently clip as a path. Note that the clip path is -
2610 given in logical coordinates. -
2611 -
2612 \warning QPainter does not store the combined clip explicitly as -
2613 this is handled by the underlying QPaintEngine, so the path is -
2614 recreated on demand and transformed to the current logical -
2615 coordinate system. This is potentially an expensive operation. -
2616 -
2617 \sa setClipPath(), clipRegion(), setClipping() -
2618*/ -
2619QPainterPath QPainter::clipPath() const -
2620{ -
2621 Q_D(const QPainter); -
2622 -
2623 // ### Since we do not support path intersections and path unions yet, -
2624 // we just use clipRegion() here... -
2625 if (!d->engine) { -
2626 qWarning("QPainter::clipPath: Painter not active"); -
2627 return QPainterPath(); -
2628 } -
2629 -
2630 // No clip, return empty -
2631 if (d->state->clipInfo.size() == 0) { -
2632 return QPainterPath(); -
2633 } else { -
2634 -
2635 // Update inverse matrix, used below. -
2636 if (!d->txinv) -
2637 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix(); -
2638 -
2639 // For the simple case avoid conversion. -
2640 if (d->state->clipInfo.size() == 1 -
2641 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) { -
2642 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix); -
2643 return d->state->clipInfo.at(0).path * matrix; -
2644 -
2645 } else if (d->state->clipInfo.size() == 1 -
2646 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) { -
2647 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix); -
2648 QPainterPath path; -
2649 path.addRect(d->state->clipInfo.at(0).rect); -
2650 return path * matrix; -
2651 } else { -
2652 // Fallback to clipRegion() for now, since we don't have isect/unite for paths -
2653 return qt_regionToPath(clipRegion()); -
2654 } -
2655 } -
2656} -
2657 -
2658/*! -
2659 Returns the bounding rectangle of the current clip if there is a clip; -
2660 otherwise returns an empty rectangle. Note that the clip region is -
2661 given in logical coordinates. -
2662 -
2663 The bounding rectangle is not guaranteed to be tight. -
2664 -
2665 \sa setClipRect(), setClipPath(), setClipRegion() -
2666 -
2667 \since 4.8 -
2668 */ -
2669 -
2670QRectF QPainter::clipBoundingRect() const -
2671{ -
2672 Q_D(const QPainter); -
2673 -
2674 if (!d->engine) { -
2675 qWarning("QPainter::clipBoundingRect: Painter not active"); -
2676 return QRectF(); -
2677 } -
2678 -
2679 // Accumulate the bounding box in device space. This is not 100% -
2680 // precise, but it fits within the guarantee and it is reasonably -
2681 // fast. -
2682 QRectF bounds; -
2683 for (int i=0; i<d->state->clipInfo.size(); ++i) { -
2684 QRectF r; -
2685 const QPainterClipInfo &info = d->state->clipInfo.at(i); -
2686 -
2687 if (info.clipType == QPainterClipInfo::RectClip) -
2688 r = info.rect; -
2689 else if (info.clipType == QPainterClipInfo::RectFClip) -
2690 r = info.rectf; -
2691 else if (info.clipType == QPainterClipInfo::RegionClip) -
2692 r = info.region.boundingRect(); -
2693 else -
2694 r = info.path.boundingRect(); -
2695 -
2696 r = info.matrix.mapRect(r); -
2697 -
2698 if (i == 0) -
2699 bounds = r; -
2700 else if (info.operation == Qt::IntersectClip) -
2701 bounds &= r; -
2702 } -
2703 -
2704 -
2705 // Map the rectangle back into logical space using the inverse -
2706 // matrix. -
2707 if (!d->txinv) -
2708 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix(); -
2709 -
2710 return d->invMatrix.mapRect(bounds); -
2711} -
2712 -
2713/*! -
2714 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation) -
2715 -
2716 Enables clipping, and sets the clip region to the given \a -
2717 rectangle using the given clip \a operation. The default operation -
2718 is to replace the current clip rectangle. -
2719 -
2720 Note that the clip rectangle is specified in logical (painter) -
2721 coordinates. -
2722 -
2723 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping} -
2724*/ -
2725void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op) -
2726{ -
2727 Q_D(QPainter); -
2728 -
2729 if (d->extended) { -
2730 if ((!d->state->clipEnabled && op != Qt::NoClip)) -
2731 op = Qt::ReplaceClip; -
2732 -
2733 if (!d->engine) { -
2734 qWarning("QPainter::setClipRect: Painter not active"); -
2735 return; -
2736 } -
2737 qreal right = rect.x() + rect.width(); -
2738 qreal bottom = rect.y() + rect.height(); -
2739 qreal pts[] = { rect.x(), rect.y(), -
2740 right, rect.y(), -
2741 right, bottom, -
2742 rect.x(), bottom }; -
2743 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint); -
2744 d->state->clipEnabled = true; -
2745 d->extended->clip(vp, op); -
2746 if (op == Qt::ReplaceClip || op == Qt::NoClip) -
2747 d->state->clipInfo.clear(); -
2748 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); -
2749 d->state->clipOperation = op; -
2750 return; -
2751 } -
2752 -
2753 if (qreal(int(rect.top())) == rect.top() -
2754 && qreal(int(rect.bottom())) == rect.bottom() -
2755 && qreal(int(rect.left())) == rect.left() -
2756 && qreal(int(rect.right())) == rect.right()) -
2757 { -
2758 setClipRect(rect.toRect(), op); -
2759 return; -
2760 } -
2761 -
2762 if (rect.isEmpty()) { -
2763 setClipRegion(QRegion(), op); -
2764 return; -
2765 } -
2766 -
2767 QPainterPath path; -
2768 path.addRect(rect); -
2769 setClipPath(path, op); -
2770} -
2771 -
2772/*! -
2773 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation) -
2774 \overload -
2775 -
2776 Enables clipping, and sets the clip region to the given \a rectangle using the given -
2777 clip \a operation. -
2778*/ -
2779void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op) -
2780{ -
2781 Q_D(QPainter); -
2782 -
2783 if (!d->engine) { -
2784 qWarning("QPainter::setClipRect: Painter not active"); -
2785 return; -
2786 } -
2787 -
2788 if ((!d->state->clipEnabled && op != Qt::NoClip)) -
2789 op = Qt::ReplaceClip; -
2790 -
2791 if (d->extended) { -
2792 d->state->clipEnabled = true; -
2793 d->extended->clip(rect, op); -
2794 if (op == Qt::ReplaceClip || op == Qt::NoClip) -
2795 d->state->clipInfo.clear(); -
2796 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); -
2797 d->state->clipOperation = op; -
2798 return; -
2799 } -
2800 -
2801 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip) -
2802 op = Qt::ReplaceClip; -
2803 -
2804 d->state->clipRegion = rect; -
2805 d->state->clipOperation = op; -
2806 if (op == Qt::NoClip || op == Qt::ReplaceClip) -
2807 d->state->clipInfo.clear(); -
2808 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); -
2809 d->state->clipEnabled = true; -
2810 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled; -
2811 d->updateState(d->state); -
2812} -
2813 -
2814/*! -
2815 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation) -
2816 -
2817 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y) -
2818 with the given \a width and \a height. -
2819*/ -
2820 -
2821/*! -
2822 \fn void QPainter::setClipRegion(const QRegion &region, Qt::ClipOperation operation) -
2823 -
2824 Sets the clip region to the given \a region using the specified clip -
2825 \a operation. The default clip operation is to replace the current -
2826 clip region. -
2827 -
2828 Note that the clip region is given in logical coordinates. -
2829 -
2830 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping} -
2831*/ -
2832void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) -
2833{ -
2834 Q_D(QPainter); -
2835#ifdef QT_DEBUG_DRAW -
2836 QRect rect = r.boundingRect(); -
2837 if (qt_show_painter_debug_output) -
2838 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n", -
2839 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height()); -
2840#endif -
2841 if (!d->engine) { -
2842 qWarning("QPainter::setClipRegion: Painter not active"); -
2843 return; -
2844 } -
2845 -
2846 if ((!d->state->clipEnabled && op != Qt::NoClip)) -
2847 op = Qt::ReplaceClip; -
2848 -
2849 if (d->extended) { -
2850 d->state->clipEnabled = true; -
2851 d->extended->clip(r, op); -
2852 if (op == Qt::NoClip || op == Qt::ReplaceClip) -
2853 d->state->clipInfo.clear(); -
2854 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix); -
2855 d->state->clipOperation = op; -
2856 return; -
2857 } -
2858 -
2859 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip) -
2860 op = Qt::ReplaceClip; -
2861 -
2862 d->state->clipRegion = r; -
2863 d->state->clipOperation = op; -
2864 if (op == Qt::NoClip || op == Qt::ReplaceClip) -
2865 d->state->clipInfo.clear(); -
2866 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix); -
2867 d->state->clipEnabled = true; -
2868 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled; -
2869 d->updateState(d->state); -
2870} -
2871 -
2872/*! -
2873 \since 4.2 -
2874 \obsolete -
2875 -
2876 Sets the transformation matrix to \a matrix and enables transformations. -
2877 -
2878 \note It is advisable to use setWorldTransform() instead of this function to -
2879 preserve the properties of perspective transformations. -
2880 -
2881 If \a combine is true, then \a matrix is combined with the current -
2882 transformation matrix; otherwise \a matrix replaces the current -
2883 transformation matrix. -
2884 -
2885 If \a matrix is the identity matrix and \a combine is false, this -
2886 function calls setWorldMatrixEnabled(false). (The identity matrix is the -
2887 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the -
2888 rest are 0.0.) -
2889 -
2890 The following functions can transform the coordinate system without using -
2891 a QMatrix: -
2892 \list -
2893 \li translate() -
2894 \li scale() -
2895 \li shear() -
2896 \li rotate() -
2897 \endlist -
2898 -
2899 They operate on the painter's worldMatrix() and are implemented like this: -
2900 -
2901 \snippet code/src_gui_painting_qpainter.cpp 4 -
2902 -
2903 Note that when using setWorldMatrix() function you should always have -
2904 \a combine be true when you are drawing into a QPicture. Otherwise -
2905 it may not be possible to replay the picture with additional -
2906 transformations; using the translate(), scale(), etc. convenience -
2907 functions is safe. -
2908 -
2909 For more information about the coordinate system, transformations -
2910 and window-viewport conversion, see \l {Coordinate System}. -
2911 -
2912 \sa setWorldTransform(), QTransform -
2913*/ -
2914 -
2915void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine) -
2916{ -
2917 setWorldTransform(QTransform(matrix), combine); -
2918} -
2919 -
2920/*! -
2921 \since 4.2 -
2922 \obsolete -
2923 -
2924 Returns the world transformation matrix. -
2925 -
2926 It is advisable to use worldTransform() because worldMatrix() does not -
2927 preserve the properties of perspective transformations. -
2928 -
2929 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations}, -
2930 {Coordinate System} -
2931*/ -
2932 -
2933const QMatrix &QPainter::worldMatrix() const -
2934{ -
2935 Q_D(const QPainter); -
2936 if (!d->engine) { -
2937 qWarning("QPainter::worldMatrix: Painter not active"); -
2938 return d->fakeState()->transform.toAffine(); -
2939 } -
2940 return d->state->worldMatrix.toAffine(); -
2941} -
2942 -
2943/*! -
2944 \obsolete -
2945 -
2946 Use setWorldTransform() instead. -
2947 -
2948 \sa setWorldTransform() -
2949*/ -
2950 -
2951void QPainter::setMatrix(const QMatrix &matrix, bool combine) -
2952{ -
2953 setWorldTransform(QTransform(matrix), combine); -
2954} -
2955 -
2956/*! -
2957 \obsolete -
2958 -
2959 Use worldTransform() instead. -
2960 -
2961 \sa worldTransform() -
2962*/ -
2963 -
2964const QMatrix &QPainter::matrix() const -
2965{ -
2966 return worldMatrix(); -
2967} -
2968 -
2969 -
2970/*! -
2971 \since 4.2 -
2972 \obsolete -
2973 -
2974 Returns the transformation matrix combining the current -
2975 window/viewport and world transformation. -
2976 -
2977 It is advisable to use combinedTransform() instead of this -
2978 function to preserve the properties of perspective transformations. -
2979 -
2980 \sa setWorldTransform(), setWindow(), setViewport() -
2981*/ -
2982QMatrix QPainter::combinedMatrix() const -
2983{ -
2984 return combinedTransform().toAffine(); -
2985} -
2986 -
2987 -
2988/*! -
2989 \obsolete -
2990 -
2991 Returns the matrix that transforms from logical coordinates to -
2992 device coordinates of the platform dependent paint device. -
2993 -
2994 \note It is advisable to use deviceTransform() instead of this -
2995 function to preserve the properties of perspective transformations. -
2996 -
2997 This function is \e only needed when using platform painting -
2998 commands on the platform dependent handle (Qt::HANDLE), and the -
2999 platform does not do transformations nativly. -
3000 -
3001 The QPaintEngine::PaintEngineFeature enum can be queried to -
3002 determine whether the platform performs the transformations or -
3003 not. -
3004 -
3005 \sa worldMatrix(), QPaintEngine::hasFeature(), -
3006*/ -
3007const QMatrix &QPainter::deviceMatrix() const -
3008{ -
3009 Q_D(const QPainter); -
3010 if (!d->engine) { -
3011 qWarning("QPainter::deviceMatrix: Painter not active"); -
3012 return d->fakeState()->transform.toAffine(); -
3013 } -
3014 return d->state->matrix.toAffine(); -
3015} -
3016 -
3017/*! -
3018 \obsolete -
3019 -
3020 Resets any transformations that were made using translate(), scale(), -
3021 shear(), rotate(), setWorldMatrix(), setViewport() and -
3022 setWindow(). -
3023 -
3024 It is advisable to use resetTransform() instead of this function -
3025 to preserve the properties of perspective transformations. -
3026 -
3027 \sa {QPainter#Coordinate Transformations}{Coordinate -
3028 Transformations} -
3029*/ -
3030 -
3031void QPainter::resetMatrix() -
3032{ -
3033 resetTransform(); -
3034} -
3035 -
3036 -
3037/*! -
3038 \since 4.2 -
3039 -
3040 Enables transformations if \a enable is true, or disables -
3041 transformations if \a enable is false. The world transformation -
3042 matrix is not changed. -
3043 -
3044 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate -
3045 Transformations}{Coordinate Transformations} -
3046*/ -
3047 -
3048void QPainter::setWorldMatrixEnabled(bool enable) -
3049{ -
3050 Q_D(QPainter); -
3051#ifdef QT_DEBUG_DRAW -
3052 if (qt_show_painter_debug_output) -
3053 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable); -
3054#endif -
3055 -
3056 if (!d->engine) { -
3057 qWarning("QPainter::setMatrixEnabled: Painter not active"); -
3058 return; -
3059 } -
3060 if (enable == d->state->WxF) -
3061 return; -
3062 -
3063 d->state->WxF = enable; -
3064 d->updateMatrix(); -
3065} -
3066 -
3067/*! -
3068 \since 4.2 -
3069 -
3070 Returns true if world transformation is enabled; otherwise returns -
3071 false. -
3072 -
3073 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System} -
3074*/ -
3075 -
3076bool QPainter::worldMatrixEnabled() const -
3077{ -
3078 Q_D(const QPainter); -
3079 if (!d->engine) { -
3080 qWarning("QPainter::worldMatrixEnabled: Painter not active"); -
3081 return false; -
3082 } -
3083 return d->state->WxF; -
3084} -
3085 -
3086/*! -
3087 \obsolete -
3088 -
3089 Use setWorldMatrixEnabled() instead. -
3090 -
3091 \sa setWorldMatrixEnabled() -
3092*/ -
3093 -
3094void QPainter::setMatrixEnabled(bool enable) -
3095{ -
3096 setWorldMatrixEnabled(enable); -
3097} -
3098 -
3099/*! -
3100 \obsolete -
3101 -
3102 Use worldMatrixEnabled() instead -
3103 -
3104 \sa worldMatrixEnabled() -
3105*/ -
3106 -
3107bool QPainter::matrixEnabled() const -
3108{ -
3109 return worldMatrixEnabled(); -
3110} -
3111 -
3112/*! -
3113 Scales the coordinate system by (\a{sx}, \a{sy}). -
3114 -
3115 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations} -
3116*/ -
3117 -
3118void QPainter::scale(qreal sx, qreal sy) -
3119{ -
3120#ifdef QT_DEBUG_DRAW -
3121 if (qt_show_painter_debug_output) -
3122 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy); -
3123#endif -
3124 Q_D(QPainter); -
3125 if (!d->engine) { -
3126 qWarning("QPainter::scale: Painter not active"); -
3127 return; -
3128 } -
3129 -
3130 d->state->worldMatrix.scale(sx,sy); -
3131 d->state->WxF = true; -
3132 d->updateMatrix(); -
3133} -
3134 -
3135/*! -
3136 Shears the coordinate system by (\a{sh}, \a{sv}). -
3137 -
3138 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations} -
3139*/ -
3140 -
3141void QPainter::shear(qreal sh, qreal sv) -
3142{ -
3143#ifdef QT_DEBUG_DRAW -
3144 if (qt_show_painter_debug_output) -
3145 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv); -
3146#endif -
3147 Q_D(QPainter); -
3148 if (!d->engine) { -
3149 qWarning("QPainter::shear: Painter not active"); -
3150 return; -
3151 } -
3152 -
3153 d->state->worldMatrix.shear(sh, sv); -
3154 d->state->WxF = true; -
3155 d->updateMatrix(); -
3156} -
3157 -
3158/*! -
3159 \fn void QPainter::rotate(qreal angle) -
3160 -
3161 Rotates the coordinate system clockwise. The given \a angle parameter uses degree unit. -
3162 -
3163 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations} -
3164*/ -
3165 -
3166void QPainter::rotate(qreal a) -
3167{ -
3168#ifdef QT_DEBUG_DRAW -
3169 if (qt_show_painter_debug_output) -
3170 printf("QPainter::rotate(), angle=%f\n", a); -
3171#endif -
3172 Q_D(QPainter); -
3173 if (!d->engine) { -
3174 qWarning("QPainter::rotate: Painter not active"); -
3175 return; -
3176 } -
3177 -
3178 d->state->worldMatrix.rotate(a); -
3179 d->state->WxF = true; -
3180 d->updateMatrix(); -
3181} -
3182 -
3183/*! -
3184 Translates the coordinate system by the given \a offset; i.e. the -
3185 given \a offset is added to points. -
3186 -
3187 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations} -
3188*/ -
3189void QPainter::translate(const QPointF &offset) -
3190{ -
3191 qreal dx = offset.x(); -
3192 qreal dy = offset.y(); -
3193#ifdef QT_DEBUG_DRAW -
3194 if (qt_show_painter_debug_output) -
3195 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy); -
3196#endif -
3197 Q_D(QPainter); -
3198 if (!d->engine) { -
3199 qWarning("QPainter::translate: Painter not active"); -
3200 return; -
3201 } -
3202 -
3203 d->state->worldMatrix.translate(dx, dy); -
3204 d->state->WxF = true; -
3205 d->updateMatrix(); -
3206} -
3207 -
3208/*! -
3209 \fn void QPainter::translate(const QPoint &offset) -
3210 \overload -
3211 -
3212 Translates the coordinate system by the given \a offset. -
3213*/ -
3214 -
3215/*! -
3216 \fn void QPainter::translate(qreal dx, qreal dy) -
3217 \overload -
3218 -
3219 Translates the coordinate system by the vector (\a dx, \a dy). -
3220*/ -
3221 -
3222/*! -
3223 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation) -
3224 -
3225 Enables clipping, and sets the clip path for the painter to the -
3226 given \a path, with the clip \a operation. -
3227 -
3228 Note that the clip path is specified in logical (painter) -
3229 coordinates. -
3230 -
3231 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping} -
3232 -
3233*/ -
3234void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op) -
3235{ -
3236#ifdef QT_DEBUG_DRAW -
3237 if (qt_show_painter_debug_output) { -
3238 QRectF b = path.boundingRect(); -
3239 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n", -
3240 path.elementCount(), op, b.x(), b.y(), b.width(), b.height()); -
3241 } -
3242#endif -
3243 Q_D(QPainter); -
3244 -
3245 if (!d->engine) { -
3246 qWarning("QPainter::setClipPath: Painter not active"); -
3247 return; -
3248 } -
3249 -
3250 if ((!d->state->clipEnabled && op != Qt::NoClip)) -
3251 op = Qt::ReplaceClip; -
3252 -
3253 if (d->extended) { -
3254 d->state->clipEnabled = true; -
3255 d->extended->clip(path, op); -
3256 if (op == Qt::NoClip || op == Qt::ReplaceClip) -
3257 d->state->clipInfo.clear(); -
3258 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix); -
3259 d->state->clipOperation = op; -
3260 return; -
3261 } -
3262 -
3263 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip) -
3264 op = Qt::ReplaceClip; -
3265 -
3266 d->state->clipPath = path; -
3267 d->state->clipOperation = op; -
3268 if (op == Qt::NoClip || op == Qt::ReplaceClip) -
3269 d->state->clipInfo.clear(); -
3270 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix); -
3271 d->state->clipEnabled = true; -
3272 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled; -
3273 d->updateState(d->state); -
3274} -
3275 -
3276/*! -
3277 Draws the outline (strokes) the path \a path with the pen specified -
3278 by \a pen -
3279 -
3280 \sa fillPath(), {QPainter#Drawing}{Drawing} -
3281*/ -
3282void QPainter::strokePath(const QPainterPath &path, const QPen &pen) -
3283{ -
3284 Q_D(QPainter); -
3285 -
3286 if (!d->engine) { -
3287 qWarning("QPainter::strokePath: Painter not active"); -
3288 return; -
3289 } -
3290 -
3291 if (path.isEmpty()) -
3292 return; -
3293 -
3294 if (d->extended) { -
3295 const QGradient *g = qpen_brush(pen).gradient(); -
3296 if (!g || g->coordinateMode() == QGradient::LogicalMode) { -
3297 d->extended->stroke(qtVectorPathForPath(path), pen); -
3298 return; -
3299 } -
3300 } -
3301 -
3302 QBrush oldBrush = d->state->brush; -
3303 QPen oldPen = d->state->pen; -
3304 -
3305 setPen(pen); -
3306 setBrush(Qt::NoBrush); -
3307 -
3308 drawPath(path); -
3309 -
3310 // Reset old state -
3311 setPen(oldPen); -
3312 setBrush(oldBrush); -
3313} -
3314 -
3315/*! -
3316 Fills the given \a path using the given \a brush. The outline is -
3317 not drawn. -
3318 -
3319 Alternatively, you can specify a QColor instead of a QBrush; the -
3320 QBrush constructor (taking a QColor argument) will automatically -
3321 create a solid pattern brush. -
3322 -
3323 \sa drawPath() -
3324*/ -
3325void QPainter::fillPath(const QPainterPath &path, const QBrush &brush) -
3326{ -
3327 Q_D(QPainter); -
3328 -
3329 if (!d->engine) { -
3330 qWarning("QPainter::fillPath: Painter not active"); -
3331 return; -
3332 } -
3333 -
3334 if (path.isEmpty()) -
3335 return; -
3336 -
3337 if (d->extended) { -
3338 const QGradient *g = brush.gradient(); -
3339 if (!g || g->coordinateMode() == QGradient::LogicalMode) { -
3340 d->extended->fill(qtVectorPathForPath(path), brush); -
3341 return; -
3342 } -
3343 } -
3344 -
3345 QBrush oldBrush = d->state->brush; -
3346 QPen oldPen = d->state->pen; -
3347 -
3348 setPen(Qt::NoPen); -
3349 setBrush(brush); -
3350 -
3351 drawPath(path); -
3352 -
3353 // Reset old state -
3354 setPen(oldPen); -
3355 setBrush(oldBrush); -
3356} -
3357 -
3358/*! -
3359 Draws the given painter \a path using the current pen for outline -
3360 and the current brush for filling. -
3361 -
3362 \table 100% -
3363 \row -
3364 \li \inlineimage qpainter-path.png -
3365 \li -
3366 \snippet code/src_gui_painting_qpainter.cpp 5 -
3367 \endtable -
3368 -
3369 \sa {painting/painterpaths}{the Painter Paths -
3370 example},{painting/deform}{the Vector Deformation example} -
3371*/ -
3372void QPainter::drawPath(const QPainterPath &path) -
3373{ -
3374#ifdef QT_DEBUG_DRAW -
3375 QRectF pathBounds = path.boundingRect(); -
3376 if (qt_show_painter_debug_output) -
3377 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n", -
3378 path.elementCount(), -
3379 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height()); -
3380#endif -
3381 -
3382 Q_D(QPainter); -
3383 -
3384 if (!d->engine) { -
3385 qWarning("QPainter::drawPath: Painter not active"); -
3386 return; -
3387 } -
3388 -
3389 if (d->extended) { -
3390 d->extended->drawPath(path); -
3391 return; -
3392 } -
3393 d->updateState(d->state); -
3394 -
3395 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) { -
3396 d->engine->drawPath(path); -
3397 } else { -
3398 d->draw_helper(path); -
3399 } -
3400} -
3401 -
3402/*! -
3403 \fn void QPainter::drawLine(const QLineF &line) -
3404 -
3405 Draws a line defined by \a line. -
3406 -
3407 \table 100% -
3408 \row -
3409 \li \inlineimage qpainter-line.png -
3410 \li -
3411 \snippet code/src_gui_painting_qpainter.cpp 6 -
3412 \endtable -
3413 -
3414 \sa drawLines(), drawPolyline(), {Coordinate System} -
3415*/ -
3416 -
3417/*! -
3418 \fn void QPainter::drawLine(const QLine &line) -
3419 \overload -
3420 -
3421 Draws a line defined by \a line. -
3422*/ -
3423 -
3424/*! -
3425 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2) -
3426 \overload -
3427 -
3428 Draws a line from \a p1 to \a p2. -
3429*/ -
3430 -
3431/*! -
3432 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2) -
3433 \overload -
3434 -
3435 Draws a line from \a p1 to \a p2. -
3436*/ -
3437 -
3438/*! -
3439 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2) -
3440 \overload -
3441 -
3442 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the -
3443 current pen position to (\a x2, \a y2). -
3444*/ -
3445 -
3446/*! -
3447 \fn void QPainter::drawRect(const QRectF &rectangle) -
3448 -
3449 Draws the current \a rectangle with the current pen and brush. -
3450 -
3451 A filled rectangle has a size of \a{rectangle}.size(). A stroked -
3452 rectangle has a size of \a{rectangle}.size() plus the pen width. -
3453 -
3454 \table 100% -
3455 \row -
3456 \li \inlineimage qpainter-rectangle.png -
3457 \li -
3458 \snippet code/src_gui_painting_qpainter.cpp 7 -
3459 \endtable -
3460 -
3461 \sa drawRects(), drawPolygon(), {Coordinate System} -
3462*/ -
3463 -
3464/*! -
3465 \fn void QPainter::drawRect(const QRect &rectangle) -
3466 -
3467 \overload -
3468 -
3469 Draws the current \a rectangle with the current pen and brush. -
3470*/ -
3471 -
3472/*! -
3473 \fn void QPainter::drawRect(int x, int y, int width, int height) -
3474 -
3475 \overload -
3476 -
3477 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and -
3478 with the given \a width and \a height. -
3479*/ -
3480 -
3481/*! -
3482 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount) -
3483 -
3484 Draws the first \a rectCount of the given \a rectangles using the -
3485 current pen and brush. -
3486 -
3487 \sa drawRect() -
3488*/ -
3489void QPainter::drawRects(const QRectF *rects, int rectCount) -
3490{ -
3491#ifdef QT_DEBUG_DRAW -
3492 if (qt_show_painter_debug_output) -
3493 printf("QPainter::drawRects(), count=%d\n", rectCount); -
3494#endif -
3495 Q_D(QPainter); -
3496 -
3497 if (!d->engine) { -
3498 qWarning("QPainter::drawRects: Painter not active"); -
3499 return; -
3500 } -
3501 -
3502 if (rectCount <= 0) -
3503 return; -
3504 -
3505 if (d->extended) { -
3506 d->extended->drawRects(rects, rectCount); -
3507 return; -
3508 } -
3509 -
3510 d->updateState(d->state); -
3511 -
3512 if (!d->state->emulationSpecifier) { -
3513 d->engine->drawRects(rects, rectCount); -
3514 return; -
3515 } -
3516 -
3517 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform -
3518 && d->state->matrix.type() == QTransform::TxTranslate) { -
3519 for (int i=0; i<rectCount; ++i) { -
3520 QRectF r(rects[i].x() + d->state->matrix.dx(), -
3521 rects[i].y() + d->state->matrix.dy(), -
3522 rects[i].width(), -
3523 rects[i].height()); -
3524 d->engine->drawRects(&r, 1); -
3525 } -
3526 } else { -
3527 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) { -
3528 for (int i=0; i<rectCount; ++i) { -
3529 QPainterPath rectPath; -
3530 rectPath.addRect(rects[i]); -
3531 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw); -
3532 } -
3533 } else { -
3534 QPainterPath rectPath; -
3535 for (int i=0; i<rectCount; ++i) -
3536 rectPath.addRect(rects[i]); -
3537 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw); -
3538 } -
3539 } -
3540} -
3541 -
3542/*! -
3543 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount) -
3544 \overload -
3545 -
3546 Draws the first \a rectCount of the given \a rectangles using the -
3547 current pen and brush. -
3548*/ -
3549void QPainter::drawRects(const QRect *rects, int rectCount) -
3550{ -
3551#ifdef QT_DEBUG_DRAW -
3552 if (qt_show_painter_debug_output) -
3553 printf("QPainter::drawRects(), count=%d\n", rectCount); -
3554#endif -
3555 Q_D(QPainter); -
3556 -
3557 if (!d->engine) { -
3558 qWarning("QPainter::drawRects: Painter not active"); -
3559 return; -
3560 } -
3561 -
3562 if (rectCount <= 0) -
3563 return; -
3564 -
3565 if (d->extended) { -
3566 d->extended->drawRects(rects, rectCount); -
3567 return; -
3568 } -
3569 -
3570 d->updateState(d->state); -
3571 -
3572 if (!d->state->emulationSpecifier) { -
3573 d->engine->drawRects(rects, rectCount); -
3574 return; -
3575 } -
3576 -
3577 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform -
3578 && d->state->matrix.type() == QTransform::TxTranslate) { -
3579 for (int i=0; i<rectCount; ++i) { -
3580 QRectF r(rects[i].x() + d->state->matrix.dx(), -
3581 rects[i].y() + d->state->matrix.dy(), -
3582 rects[i].width(), -
3583 rects[i].height()); -
3584 -
3585 d->engine->drawRects(&r, 1); -
3586 } -
3587 } else { -
3588 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) { -
3589 for (int i=0; i<rectCount; ++i) { -
3590 QPainterPath rectPath; -
3591 rectPath.addRect(rects[i]); -
3592 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw); -
3593 } -
3594 } else { -
3595 QPainterPath rectPath; -
3596 for (int i=0; i<rectCount; ++i) -
3597 rectPath.addRect(rects[i]); -
3598 -
3599 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw); -
3600 } -
3601 } -
3602} -
3603 -
3604/*! -
3605 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles) -
3606 \overload -
3607 -
3608 Draws the given \a rectangles using the current pen and brush. -
3609*/ -
3610 -
3611/*! -
3612 \fn void QPainter::drawRects(const QVector<QRect> &rectangles) -
3613 -
3614 \overload -
3615 -
3616 Draws the given \a rectangles using the current pen and brush. -
3617*/ -
3618 -
3619/*! -
3620 \fn void QPainter::drawPoint(const QPointF &position) -
3621 -
3622 Draws a single point at the given \a position using the current -
3623 pen's color. -
3624 -
3625 \sa {Coordinate System} -
3626*/ -
3627 -
3628/*! -
3629 \fn void QPainter::drawPoint(const QPoint &position) -
3630 \overload -
3631 -
3632 Draws a single point at the given \a position using the current -
3633 pen's color. -
3634*/ -
3635 -
3636/*! \fn void QPainter::drawPoint(int x, int y) -
3637 -
3638 \overload -
3639 -
3640 Draws a single point at position (\a x, \a y). -
3641*/ -
3642 -
3643/*! -
3644 Draws the first \a pointCount points in the array \a points using -
3645 the current pen's color. -
3646 -
3647 \sa {Coordinate System} -
3648*/ -
3649void QPainter::drawPoints(const QPointF *points, int pointCount) -
3650{ -
3651#ifdef QT_DEBUG_DRAW -
3652 if (qt_show_painter_debug_output) -
3653 printf("QPainter::drawPoints(), count=%d\n", pointCount); -
3654#endif -
3655 Q_D(QPainter); -
3656 -
3657 if (!d->engine) { -
3658 qWarning("QPainter::drawPoints: Painter not active"); -
3659 return; -
3660 } -
3661 -
3662 if (pointCount <= 0) -
3663 return; -
3664 -
3665 if (d->extended) { -
3666 d->extended->drawPoints(points, pointCount); -
3667 return; -
3668 } -
3669 -
3670 d->updateState(d->state); -
3671 -
3672 if (!d->state->emulationSpecifier) { -
3673 d->engine->drawPoints(points, pointCount); -
3674 return; -
3675 } -
3676 -
3677 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform -
3678 && d->state->matrix.type() == QTransform::TxTranslate) { -
3679 // ### use drawPoints function -
3680 for (int i=0; i<pointCount; ++i) { -
3681 QPointF pt(points[i].x() + d->state->matrix.dx(), -
3682 points[i].y() + d->state->matrix.dy()); -
3683 d->engine->drawPoints(&pt, 1); -
3684 } -
3685 } else { -
3686 QPen pen = d->state->pen; -
3687 bool flat_pen = pen.capStyle() == Qt::FlatCap; -
3688 if (flat_pen) { -
3689 save(); -
3690 pen.setCapStyle(Qt::SquareCap); -
3691 setPen(pen); -
3692 } -
3693 QPainterPath path; -
3694 for (int i=0; i<pointCount; ++i) { -
3695 path.moveTo(points[i].x(), points[i].y()); -
3696 path.lineTo(points[i].x() + 0.0001, points[i].y()); -
3697 } -
3698 d->draw_helper(path, QPainterPrivate::StrokeDraw); -
3699 if (flat_pen) -
3700 restore(); -
3701 } -
3702} -
3703 -
3704/*! -
3705 \overload -
3706 -
3707 Draws the first \a pointCount points in the array \a points using -
3708 the current pen's color. -
3709*/ -
3710 -
3711void QPainter::drawPoints(const QPoint *points, int pointCount) -
3712{ -
3713#ifdef QT_DEBUG_DRAW -
3714 if (qt_show_painter_debug_output) -
3715 printf("QPainter::drawPoints(), count=%d\n", pointCount); -
3716#endif -
3717 Q_D(QPainter); -
3718 -
3719 if (!d->engine) { -
3720 qWarning("QPainter::drawPoints: Painter not active"); -
3721 return; -
3722 } -
3723 -
3724 if (pointCount <= 0) -
3725 return; -
3726 -
3727 if (d->extended) { -
3728 d->extended->drawPoints(points, pointCount); -
3729 return; -
3730 } -
3731 -
3732 d->updateState(d->state); -
3733 -
3734 if (!d->state->emulationSpecifier) { -
3735 d->engine->drawPoints(points, pointCount); -
3736 return; -
3737 } -
3738 -
3739 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform -
3740 && d->state->matrix.type() == QTransform::TxTranslate) { -
3741 // ### use drawPoints function -
3742 for (int i=0; i<pointCount; ++i) { -
3743 QPointF pt(points[i].x() + d->state->matrix.dx(), -
3744 points[i].y() + d->state->matrix.dy()); -
3745 d->engine->drawPoints(&pt, 1); -
3746 } -
3747 } else { -
3748 QPen pen = d->state->pen; -
3749 bool flat_pen = (pen.capStyle() == Qt::FlatCap); -
3750 if (flat_pen) { -
3751 save(); -
3752 pen.setCapStyle(Qt::SquareCap); -
3753 setPen(pen); -
3754 } -
3755 QPainterPath path; -
3756 for (int i=0; i<pointCount; ++i) { -
3757 path.moveTo(points[i].x(), points[i].y()); -
3758 path.lineTo(points[i].x() + 0.0001, points[i].y()); -
3759 } -
3760 d->draw_helper(path, QPainterPrivate::StrokeDraw); -
3761 if (flat_pen) -
3762 restore(); -
3763 } -
3764} -
3765 -
3766/*! -
3767 \fn void QPainter::drawPoints(const QPolygonF &points) -
3768 -
3769 \overload -
3770 -
3771 Draws the points in the vector \a points. -
3772*/ -
3773 -
3774/*! -
3775 \fn void QPainter::drawPoints(const QPolygon &points) -
3776 -
3777 \overload -
3778 -
3779 Draws the points in the vector \a points. -
3780*/ -
3781 -
3782/*! -
3783 Sets the background mode of the painter to the given \a mode -
3784 -
3785 Qt::TransparentMode (the default) draws stippled lines and text -
3786 without setting the background pixels. Qt::OpaqueMode fills these -
3787 space with the current background color. -
3788 -
3789 Note that in order to draw a bitmap or pixmap transparently, you -
3790 must use QPixmap::setMask(). -
3791 -
3792 \sa backgroundMode(), setBackground(), -
3793 {QPainter#Settings}{Settings} -
3794*/ -
3795 -
3796void QPainter::setBackgroundMode(Qt::BGMode mode) -
3797{ -
3798#ifdef QT_DEBUG_DRAW -
3799 if (qt_show_painter_debug_output) -
3800 printf("QPainter::setBackgroundMode(), mode=%d\n", mode); -
3801#endif -
3802 -
3803 Q_D(QPainter); -
3804 if (!d->engine) { -
3805 qWarning("QPainter::setBackgroundMode: Painter not active"); -
3806 return; -
3807 } -
3808 if (d->state->bgMode == mode) -
3809 return; -
3810 -
3811 d->state->bgMode = mode; -
3812 if (d->extended) { -
3813 d->checkEmulation(); -
3814 } else { -
3815 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode; -
3816 } -
3817} -
3818 -
3819/*! -
3820 Returns the current background mode. -
3821 -
3822 \sa setBackgroundMode(), {QPainter#Settings}{Settings} -
3823*/ -
3824Qt::BGMode QPainter::backgroundMode() const -
3825{ -
3826 Q_D(const QPainter); -
3827 if (!d->engine) { -
3828 qWarning("QPainter::backgroundMode: Painter not active"); -
3829 return Qt::TransparentMode; -
3830 } -
3831 return d->state->bgMode; -
3832} -
3833 -
3834 -
3835/*! -
3836 \overload -
3837 -
3838 Sets the painter's pen to have style Qt::SolidLine, width 0 and the -
3839 specified \a color. -
3840*/ -
3841 -
3842void QPainter::setPen(const QColor &color) -
3843{ -
3844#ifdef QT_DEBUG_DRAW -
3845 if (qt_show_painter_debug_output) -
3846 printf("QPainter::setPen(), color=%04x\n", color.rgb()); -
3847#endif -
3848 Q_D(QPainter); -
3849 if (!d->engine) { -
3850 qWarning("QPainter::setPen: Painter not active"); -
3851 return; -
3852 } -
3853 -
3854 QPen pen(color.isValid() ? color : QColor(Qt::black)); -
3855 -
3856 if (d->state->pen == pen) -
3857 return; -
3858 -
3859 d->state->pen = pen; -
3860 if (d->extended) -
3861 d->extended->penChanged(); -
3862 else -
3863 d->state->dirtyFlags |= QPaintEngine::DirtyPen; -
3864} -
3865 -
3866/*! -
3867 Sets the painter's pen to be the given \a pen. -
3868 -
3869 The \a pen defines how to draw lines and outlines, and it also -
3870 defines the text color. -
3871 -
3872 \sa pen(), {QPainter#Settings}{Settings} -
3873*/ -
3874 -
3875void QPainter::setPen(const QPen &pen) -
3876{ -
3877 -
3878#ifdef QT_DEBUG_DRAW -
3879 if (qt_show_painter_debug_output) -
3880 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n", -
3881 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle()); -
3882#endif -
3883 Q_D(QPainter); -
3884 if (!d->engine) { -
3885 qWarning("QPainter::setPen: Painter not active"); -
3886 return; -
3887 } -
3888 -
3889 if (d->state->pen == pen) -
3890 return; -
3891 -
3892 d->state->pen = pen; -
3893 -
3894 if (d->extended) { -
3895 d->checkEmulation(); -
3896 d->extended->penChanged(); -
3897 return; -
3898 } -
3899 -
3900 d->state->dirtyFlags |= QPaintEngine::DirtyPen; -
3901} -
3902 -
3903/*! -
3904 \overload -
3905 -
3906 Sets the painter's pen to have the given \a style, width 1 and -
3907 black color. -
3908*/ -
3909 -
3910void QPainter::setPen(Qt::PenStyle style) -
3911{ -
3912 Q_D(QPainter); -
3913 if (!d->engine) { -
3914 qWarning("QPainter::setPen: Painter not active"); -
3915 return; -
3916 } -
3917 -
3918 QPen pen = QPen(style); -
3919 -
3920 if (d->state->pen == pen) -
3921 return; -
3922 -
3923 d->state->pen = pen; -
3924 -
3925 if (d->extended) -
3926 d->extended->penChanged(); -
3927 else -
3928 d->state->dirtyFlags |= QPaintEngine::DirtyPen; -
3929 -
3930} -
3931 -
3932/*! -
3933 Returns the painter's current pen. -
3934 -
3935 \sa setPen(), {QPainter#Settings}{Settings} -
3936*/ -
3937 -
3938const QPen &QPainter::pen() const -
3939{ -
3940 Q_D(const QPainter); -
3941 if (!d->engine) { -
3942 qWarning("QPainter::pen: Painter not active"); -
3943 return d->fakeState()->pen; -
3944 } -
3945 return d->state->pen; -
3946} -
3947 -
3948 -
3949/*! -
3950 Sets the painter's brush to the given \a brush. -
3951 -
3952 The painter's brush defines how shapes are filled. -
3953 -
3954 \sa brush(), {QPainter#Settings}{Settings} -
3955*/ -
3956 -
3957void QPainter::setBrush(const QBrush &brush) -
3958{ -
3959#ifdef QT_DEBUG_DRAW -
3960 if (qt_show_painter_debug_output) -
3961 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style()); -
3962#endif -
3963 Q_D(QPainter); -
3964 if (!d->engine) { -
3965 qWarning("QPainter::setBrush: Painter not active"); -
3966 return; -
3967 } -
3968 -
3969 if (d->state->brush.d == brush.d) -
3970 return; -
3971 -
3972 if (d->extended) { -
3973 d->state->brush = brush; -
3974 d->checkEmulation(); -
3975 d->extended->brushChanged(); -
3976 return; -
3977 } -
3978 -
3979 d->state->brush = brush; -
3980 d->state->dirtyFlags |= QPaintEngine::DirtyBrush; -
3981} -
3982 -
3983 -
3984/*! -
3985 \overload -
3986 -
3987 Sets the painter's brush to black color and the specified \a -
3988 style. -
3989*/ -
3990 -
3991void QPainter::setBrush(Qt::BrushStyle style) -
3992{ -
3993 Q_D(QPainter); -
3994 if (!d->engine) { -
3995 qWarning("QPainter::setBrush: Painter not active"); -
3996 return; -
3997 } -
3998 if (d->state->brush.style() == style && -
3999 (style == Qt::NoBrush -
4000 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0)))) -
4001 return; -
4002 d->state->brush = QBrush(Qt::black, style); -
4003 if (d->extended) -
4004 d->extended->brushChanged(); -
4005 else -
4006 d->state->dirtyFlags |= QPaintEngine::DirtyBrush; -
4007} -
4008 -
4009/*! -
4010 Returns the painter's current brush. -
4011 -
4012 \sa QPainter::setBrush(), {QPainter#Settings}{Settings} -
4013*/ -
4014 -
4015const QBrush &QPainter::brush() const -
4016{ -
4017 Q_D(const QPainter); -
4018 if (!d->engine) { -
4019 qWarning("QPainter::brush: Painter not active"); -
4020 return d->fakeState()->brush; -
4021 } -
4022 return d->state->brush; -
4023} -
4024 -
4025/*! -
4026 \fn void QPainter::setBackground(const QBrush &brush) -
4027 -
4028 Sets the background brush of the painter to the given \a brush. -
4029 -
4030 The background brush is the brush that is filled in when drawing -
4031 opaque text, stippled lines and bitmaps. The background brush has -
4032 no effect in transparent background mode (which is the default). -
4033 -
4034 \sa background(), setBackgroundMode(), -
4035 {QPainter#Settings}{Settings} -
4036*/ -
4037 -
4038void QPainter::setBackground(const QBrush &bg) -
4039{ -
4040#ifdef QT_DEBUG_DRAW -
4041 if (qt_show_painter_debug_output) -
4042 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style()); -
4043#endif -
4044 -
4045 Q_D(QPainter); -
4046 if (!d->engine) { -
4047 qWarning("QPainter::setBackground: Painter not active"); -
4048 return; -
4049 } -
4050 d->state->bgBrush = bg; -
4051 if (!d->extended) -
4052 d->state->dirtyFlags |= QPaintEngine::DirtyBackground; -
4053} -
4054 -
4055/*! -
4056 Sets the painter's font to the given \a font. -
4057 -
4058 This font is used by subsequent drawText() functions. The text -
4059 color is the same as the pen color. -
4060 -
4061 If you set a font that isn't available, Qt finds a close match. -
4062 font() will return what you set using setFont() and fontInfo() returns the -
4063 font actually being used (which may be the same). -
4064 -
4065 \sa font(), drawText(), {QPainter#Settings}{Settings} -
4066*/ -
4067 -
4068void QPainter::setFont(const QFont &font) -
4069{ -
4070 Q_D(QPainter); -
4071 -
4072#ifdef QT_DEBUG_DRAW -
4073 if (qt_show_painter_debug_output) -
4074 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize()); -
4075#endif -
4076 -
4077 if (!d->engine) { -
4078 qWarning("QPainter::setFont: Painter not active"); -
4079 return; -
4080 } -
4081 -
4082 d->state->font = QFont(font.resolve(d->state->deviceFont), device()); -
4083 if (!d->extended) -
4084 d->state->dirtyFlags |= QPaintEngine::DirtyFont; -
4085} -
4086 -
4087/*! -
4088 Returns the currently set font used for drawing text. -
4089 -
4090 \sa setFont(), drawText(), {QPainter#Settings}{Settings} -
4091*/ -
4092const QFont &QPainter::font() const -
4093{ -
4094 Q_D(const QPainter); -
4095 if (!d->engine) { -
4096 qWarning("QPainter::font: Painter not active"); -
4097 return d->fakeState()->font; -
4098 } -
4099 return d->state->font; -
4100} -
4101 -
4102/*! -
4103 \since 4.4 -
4104 -
4105 Draws the given rectangle \a rect with rounded corners. -
4106 -
4107 The \a xRadius and \a yRadius arguments specify the radii -
4108 of the ellipses defining the corners of the rounded rectangle. -
4109 When \a mode is Qt::RelativeSize, \a xRadius and -
4110 \a yRadius are specified in percentage of half the rectangle's -
4111 width and height respectively, and should be in the range -
4112 0.0 to 100.0. -
4113 -
4114 A filled rectangle has a size of rect.size(). A stroked rectangle -
4115 has a size of rect.size() plus the pen width. -
4116 -
4117 \table 100% -
4118 \row -
4119 \li \inlineimage qpainter-roundrect.png -
4120 \li -
4121 \snippet code/src_gui_painting_qpainter.cpp 8 -
4122 \endtable -
4123 -
4124 \sa drawRect(), QPen -
4125*/ -
4126void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode) -
4127{ -
4128#ifdef QT_DEBUG_DRAW -
4129 if (qt_show_painter_debug_output) -
4130 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height()); -
4131#endif -
4132 Q_D(QPainter); -
4133 -
4134 if (!d->engine) -
4135 return; -
4136 -
4137 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle -
4138 drawRect(rect); -
4139 return; -
4140 } -
4141 -
4142 if (d->extended) { -
4143 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode); -
4144 return; -
4145 } -
4146 -
4147 QPainterPath path; -
4148 path.addRoundedRect(rect, xRadius, yRadius, mode); -
4149 drawPath(path); -
4150} -
4151 -
4152/*! -
4153 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius, -
4154 Qt::SizeMode mode = Qt::AbsoluteSize); -
4155 \since 4.4 -
4156 \overload -
4157 -
4158 Draws the given rectangle \a rect with rounded corners. -
4159*/ -
4160 -
4161/*! -
4162 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius, -
4163 Qt::SizeMode mode = Qt::AbsoluteSize); -
4164 \since 4.4 -
4165 \overload -
4166 -
4167 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners. -
4168*/ -
4169 -
4170/*! -
4171 \obsolete -
4172 -
4173 Draws a rectangle \a r with rounded corners. -
4174 -
4175 The \a xRnd and \a yRnd arguments specify how rounded the corners -
4176 should be. 0 is angled corners, 99 is maximum roundedness. -
4177 -
4178 A filled rectangle has a size of r.size(). A stroked rectangle -
4179 has a size of r.size() plus the pen width. -
4180 -
4181 \sa drawRoundedRect() -
4182*/ -
4183void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd) -
4184{ -
4185 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize); -
4186} -
4187 -
4188 -
4189/*! -
4190 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25) -
4191 -
4192 \overload -
4193 \obsolete -
4194 -
4195 Draws the rectangle \a r with rounded corners. -
4196*/ -
4197 -
4198/*! -
4199 \obsolete -
4200 -
4201 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd) -
4202 -
4203 \overload -
4204 -
4205 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners. -
4206*/ -
4207 -
4208/*! -
4209 \fn void QPainter::drawEllipse(const QRectF &rectangle) -
4210 -
4211 Draws the ellipse defined by the given \a rectangle. -
4212 -
4213 A filled ellipse has a size of \a{rectangle}.\l -
4214 {QRect::size()}{size()}. A stroked ellipse has a size of -
4215 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width. -
4216 -
4217 \table 100% -
4218 \row -
4219 \li \inlineimage qpainter-ellipse.png -
4220 \li -
4221 \snippet code/src_gui_painting_qpainter.cpp 9 -
4222 \endtable -
4223 -
4224 \sa drawPie(), {Coordinate System} -
4225*/ -
4226void QPainter::drawEllipse(const QRectF &r) -
4227{ -
4228#ifdef QT_DEBUG_DRAW -
4229 if (qt_show_painter_debug_output) -
4230 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height()); -
4231#endif -
4232 Q_D(QPainter); -
4233 -
4234 if (!d->engine) -
4235 return; -
4236 -
4237 QRectF rect(r.normalized()); -
4238 -
4239 if (d->extended) { -
4240 d->extended->drawEllipse(rect); -
4241 return; -
4242 } -
4243 -
4244 d->updateState(d->state); -
4245 if (d->state->emulationSpecifier) { -
4246 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform -
4247 && d->state->matrix.type() == QTransform::TxTranslate) { -
4248 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy())); -
4249 } else { -
4250 QPainterPath path; -
4251 path.addEllipse(rect); -
4252 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw); -
4253 return; -
4254 } -
4255 } -
4256 -
4257 d->engine->drawEllipse(rect); -
4258} -
4259 -
4260/*! -
4261 \fn QPainter::drawEllipse(const QRect &rectangle) -
4262 -
4263 \overload -
4264 -
4265 Draws the ellipse defined by the given \a rectangle. -
4266*/ -
4267void QPainter::drawEllipse(const QRect &r) -
4268{ -
4269#ifdef QT_DEBUG_DRAW -
4270 if (qt_show_painter_debug_output) -
4271 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height()); -
4272#endif -
4273 Q_D(QPainter); -
4274 -
4275 if (!d->engine) -
4276 return; -
4277 -
4278 QRect rect(r.normalized()); -
4279 -
4280 if (d->extended) { -
4281 d->extended->drawEllipse(rect); -
4282 return; -
4283 } -
4284 -
4285 d->updateState(d->state); -
4286 -
4287 if (d->state->emulationSpecifier) { -
4288 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform -
4289 && d->state->matrix.type() == QTransform::TxTranslate) { -
4290 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy()))); -
4291 } else { -
4292 QPainterPath path; -
4293 path.addEllipse(rect); -
4294 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw); -
4295 return; -
4296 } -
4297 } -
4298 -
4299 d->engine->drawEllipse(rect); -
4300} -
4301 -
4302/*! -
4303 \fn QPainter::drawEllipse(int x, int y, int width, int height) -
4304 -
4305 \overload -
4306 -
4307 Draws the ellipse defined by the rectangle beginning at (\a{x}, -
4308 \a{y}) with the given \a width and \a height. -
4309*/ -
4310 -
4311/*! -
4312 \since 4.4 -
4313 -
4314 \fn QPainter::drawEllipse(const QPointF &center, qreal rx, qreal ry) -
4315 -
4316 \overload -
4317 -
4318 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}. -
4319*/ -
4320 -
4321/*! -
4322 \since 4.4 -
4323 -
4324 \fn QPainter::drawEllipse(const QPoint &center, int rx, int ry) -
4325 -
4326 \overload -
4327 -
4328 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}. -
4329*/ -
4330 -
4331/*! -
4332 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle) -
4333 -
4334 Draws the arc defined by the given \a rectangle, \a startAngle and -
4335 \a spanAngle. -
4336 -
4337 The \a startAngle and \a spanAngle must be specified in 1/16th of -
4338 a degree, i.e. a full circle equals 5760 (16 * 360). Positive -
4339 values for the angles mean counter-clockwise while negative values -
4340 mean the clockwise direction. Zero degrees is at the 3 o'clock -
4341 position. -
4342 -
4343 \table 100% -
4344 \row -
4345 \li \inlineimage qpainter-arc.png -
4346 \li -
4347 \snippet code/src_gui_painting_qpainter.cpp 10 -
4348 \endtable -
4349 -
4350 \sa drawPie(), drawChord(), {Coordinate System} -
4351*/ -
4352 -
4353void QPainter::drawArc(const QRectF &r, int a, int alen) -
4354{ -
4355#ifdef QT_DEBUG_DRAW -
4356 if (qt_show_painter_debug_output) -
4357 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n", -
4358 r.x(), r.y(), r.width(), r.height(), a/16, alen/16); -
4359#endif -
4360 Q_D(QPainter); -
4361 -
4362 if (!d->engine) -
4363 return; -
4364 -
4365 QRectF rect = r.normalized(); -
4366 -
4367 QPainterPath path; -
4368 path.arcMoveTo(rect, a/16.0); -
4369 path.arcTo(rect, a/16.0, alen/16.0); -
4370 strokePath(path, d->state->pen); -
4371} -
4372 -
4373/*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle, -
4374 int spanAngle) -
4375 -
4376 \overload -
4377 -
4378 Draws the arc defined by the given \a rectangle, \a startAngle and -
4379 \a spanAngle. -
4380*/ -
4381 -
4382/*! -
4383 \fn void QPainter::drawArc(int x, int y, int width, int height, -
4384 int startAngle, int spanAngle) -
4385 -
4386 \overload -
4387 -
4388 Draws the arc defined by the rectangle beginning at (\a x, \a y) -
4389 with the specified \a width and \a height, and the given \a -
4390 startAngle and \a spanAngle. -
4391*/ -
4392 -
4393/*! -
4394 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle) -
4395 -
4396 Draws a pie defined by the given \a rectangle, \a startAngle and \a spanAngle. -
4397 -
4398 The pie is filled with the current brush(). -
4399 -
4400 The startAngle and spanAngle must be specified in 1/16th of a -
4401 degree, i.e. a full circle equals 5760 (16 * 360). Positive values -
4402 for the angles mean counter-clockwise while negative values mean -
4403 the clockwise direction. Zero degrees is at the 3 o'clock -
4404 position. -
4405 -
4406 \table 100% -
4407 \row -
4408 \li \inlineimage qpainter-pie.png -
4409 \li -
4410 \snippet code/src_gui_painting_qpainter.cpp 11 -
4411 \endtable -
4412 -
4413 \sa drawEllipse(), drawChord(), {Coordinate System} -
4414*/ -
4415void QPainter::drawPie(const QRectF &r, int a, int alen) -
4416{ -
4417#ifdef QT_DEBUG_DRAW -
4418 if (qt_show_painter_debug_output) -
4419 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n", -
4420 r.x(), r.y(), r.width(), r.height(), a/16, alen/16); -
4421#endif -
4422 Q_D(QPainter); -
4423 -
4424 if (!d->engine) -
4425 return; -
4426 -
4427 if (a > (360*16)) { -
4428 a = a % (360*16); -
4429 } else if (a < 0) { -
4430 a = a % (360*16); -
4431 if (a < 0) a += (360*16); -
4432 } -
4433 -
4434 QRectF rect = r.normalized(); -
4435 -
4436 QPainterPath path; -
4437 path.moveTo(rect.center()); -
4438 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0); -
4439 path.closeSubpath(); -
4440 drawPath(path); -
4441 -
4442} -
4443 -
4444/*! -
4445 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle) -
4446 \overload -
4447 -
4448 Draws a pie defined by the given \a rectangle, \a startAngle and -
4449 and \a spanAngle. -
4450*/ -
4451 -
4452/*! -
4453 \fn void QPainter::drawPie(int x, int y, int width, int height, int -
4454 startAngle, int spanAngle) -
4455 -
4456 \overload -
4457 -
4458 Draws the pie defined by the rectangle beginning at (\a x, \a y) with -
4459 the specified \a width and \a height, and the given \a startAngle and -
4460 \a spanAngle. -
4461*/ -
4462 -
4463/*! -
4464 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle) -
4465 -
4466 Draws the chord defined by the given \a rectangle, \a startAngle and -
4467 \a spanAngle. The chord is filled with the current brush(). -
4468 -
4469 The startAngle and spanAngle must be specified in 1/16th of a -
4470 degree, i.e. a full circle equals 5760 (16 * 360). Positive values -
4471 for the angles mean counter-clockwise while negative values mean -
4472 the clockwise direction. Zero degrees is at the 3 o'clock -
4473 position. -
4474 -
4475 \table 100% -
4476 \row -
4477 \li \inlineimage qpainter-chord.png -
4478 \li -
4479 \snippet code/src_gui_painting_qpainter.cpp 12 -
4480 \endtable -
4481 -
4482 \sa drawArc(), drawPie(), {Coordinate System} -
4483*/ -
4484void QPainter::drawChord(const QRectF &r, int a, int alen) -
4485{ -
4486#ifdef QT_DEBUG_DRAW -
4487 if (qt_show_painter_debug_output) -
4488 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n", -
4489 r.x(), r.y(), r.width(), r.height(), a/16, alen/16); -
4490#endif -
4491 Q_D(QPainter); -
4492 -
4493 if (!d->engine) -
4494 return; -
4495 -
4496 QRectF rect = r.normalized(); -
4497 -
4498 QPainterPath path; -
4499 path.arcMoveTo(rect, a/16.0); -
4500 path.arcTo(rect, a/16.0, alen/16.0); -
4501 path.closeSubpath(); -
4502 drawPath(path); -
4503} -
4504/*! -
4505 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle) -
4506 -
4507 \overload -
4508 -
4509 Draws the chord defined by the given \a rectangle, \a startAngle and -
4510 \a spanAngle. -
4511*/ -
4512 -
4513/*! -
4514 \fn void QPainter::drawChord(int x, int y, int width, int height, int -
4515 startAngle, int spanAngle) -
4516 -
4517 \overload -
4518 -
4519 Draws the chord defined by the rectangle beginning at (\a x, \a y) -
4520 with the specified \a width and \a height, and the given \a -
4521 startAngle and \a spanAngle. -
4522*/ -
4523 -
4524 -
4525/*! -
4526 Draws the first \a lineCount lines in the array \a lines -
4527 using the current pen. -
4528 -
4529 \sa drawLine(), drawPolyline() -
4530*/ -
4531void QPainter::drawLines(const QLineF *lines, int lineCount) -
4532{ -
4533#ifdef QT_DEBUG_DRAW -
4534 if (qt_show_painter_debug_output) -
4535 printf("QPainter::drawLines(), line count=%d\n", lineCount); -
4536#endif -
4537 -
4538 Q_D(QPainter); -
4539 -
4540 if (!d->engine || lineCount < 1) -
4541 return; -
4542 -
4543 if (d->extended) { -
4544 d->extended->drawLines(lines, lineCount); -
4545 return; -
4546 } -
4547 -
4548 d->updateState(d->state); -
4549 -
4550 uint lineEmulation = line_emulation(d->state->emulationSpecifier); -
4551 -
4552 if (lineEmulation) { -
4553 if (lineEmulation == QPaintEngine::PrimitiveTransform -
4554 && d->state->matrix.type() == QTransform::TxTranslate) { -
4555 for (int i = 0; i < lineCount; ++i) { -
4556 QLineF line = lines[i]; -
4557 line.translate(d->state->matrix.dx(), d->state->matrix.dy()); -
4558 d->engine->drawLines(&line, 1); -
4559 } -
4560 } else { -
4561 QPainterPath linePath; -
4562 for (int i = 0; i < lineCount; ++i) { -
4563 linePath.moveTo(lines[i].p1()); -
4564 linePath.lineTo(lines[i].p2()); -
4565 } -
4566 d->draw_helper(linePath, QPainterPrivate::StrokeDraw); -
4567 } -
4568 return; -
4569 } -
4570 d->engine->drawLines(lines, lineCount); -
4571} -
4572 -
4573/*! -
4574 \fn void QPainter::drawLines(const QLine *lines, int lineCount) -
4575 \overload -
4576 -
4577 Draws the first \a lineCount lines in the array \a lines -
4578 using the current pen. -
4579*/ -
4580void QPainter::drawLines(const QLine *lines, int lineCount) -
4581{ -
4582#ifdef QT_DEBUG_DRAW -
4583 if (qt_show_painter_debug_output) -
4584 printf("QPainter::drawLine(), line count=%d\n", lineCount); -
4585#endif -
4586 -
4587 Q_D(QPainter); -
4588 -
4589 if (!d->engine || lineCount < 1) -
4590 return; -
4591 -
4592 if (d->extended) { -
4593 d->extended->drawLines(lines, lineCount); -
4594 return; -
4595 } -
4596 -
4597 d->updateState(d->state); -
4598 -
4599 uint lineEmulation = line_emulation(d->state->emulationSpecifier); -
4600 -
4601 if (lineEmulation) { -
4602 if (lineEmulation == QPaintEngine::PrimitiveTransform -
4603 && d->state->matrix.type() == QTransform::TxTranslate) { -
4604 for (int i = 0; i < lineCount; ++i) { -
4605 QLineF line = lines[i]; -
4606 line.translate(d->state->matrix.dx(), d->state->matrix.dy()); -
4607 d->engine->drawLines(&line, 1); -
4608 } -
4609 } else { -
4610 QPainterPath linePath; -
4611 for (int i = 0; i < lineCount; ++i) { -
4612 linePath.moveTo(lines[i].p1()); -
4613 linePath.lineTo(lines[i].p2()); -
4614 } -
4615 d->draw_helper(linePath, QPainterPrivate::StrokeDraw); -
4616 } -
4617 return; -
4618 } -
4619 d->engine->drawLines(lines, lineCount); -
4620} -
4621 -
4622/*! -
4623 \overload -
4624 -
4625 Draws the first \a lineCount lines in the array \a pointPairs -
4626 using the current pen. The lines are specified as pairs of points -
4627 so the number of entries in \a pointPairs must be at least \a -
4628 lineCount * 2. -
4629*/ -
4630void QPainter::drawLines(const QPointF *pointPairs, int lineCount) -
4631{ -
4632 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF)); -
4633 -
4634 drawLines((QLineF*)pointPairs, lineCount); -
4635} -
4636 -
4637/*! -
4638 \overload -
4639 -
4640 Draws the first \a lineCount lines in the array \a pointPairs -
4641 using the current pen. -
4642*/ -
4643void QPainter::drawLines(const QPoint *pointPairs, int lineCount) -
4644{ -
4645 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint)); -
4646 -
4647 drawLines((QLine*)pointPairs, lineCount); -
4648} -
4649 -
4650 -
4651/*! -
4652 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs) -
4653 \overload -
4654 -
4655 Draws a line for each pair of points in the vector \a pointPairs -
4656 using the current pen. If there is an odd number of points in the -
4657 array, the last point will be ignored. -
4658*/ -
4659 -
4660/*! -
4661 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs) -
4662 \overload -
4663 -
4664 Draws a line for each pair of points in the vector \a pointPairs -
4665 using the current pen. -
4666*/ -
4667 -
4668/*! -
4669 \fn void QPainter::drawLines(const QVector<QLineF> &lines) -
4670 \overload -
4671 -
4672 Draws the set of lines defined by the list \a lines using the -
4673 current pen and brush. -
4674*/ -
4675 -
4676/*! -
4677 \fn void QPainter::drawLines(const QVector<QLine> &lines) -
4678 \overload -
4679 -
4680 Draws the set of lines defined by the list \a lines using the -
4681 current pen and brush. -
4682*/ -
4683 -
4684/*! -
4685 Draws the polyline defined by the first \a pointCount points in \a -
4686 points using the current pen. -
4687 -
4688 Note that unlike the drawPolygon() function the last point is \e -
4689 not connected to the first, neither is the polyline filled. -
4690 -
4691 \table 100% -
4692 \row -
4693 \li -
4694 \snippet code/src_gui_painting_qpainter.cpp 13 -
4695 \endtable -
4696 -
4697 \sa drawLines(), drawPolygon(), {Coordinate System} -
4698*/ -
4699void QPainter::drawPolyline(const QPointF *points, int pointCount) -
4700{ -
4701#ifdef QT_DEBUG_DRAW -
4702 if (qt_show_painter_debug_output) -
4703 printf("QPainter::drawPolyline(), count=%d\n", pointCount); -
4704#endif -
4705 Q_D(QPainter); -
4706 -
4707 if (!d->engine || pointCount < 2) -
4708 return; -
4709 -
4710 if (d->extended) { -
4711 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode); -
4712 return; -
4713 } -
4714 -
4715 d->updateState(d->state); -
4716 -
4717 uint lineEmulation = line_emulation(d->state->emulationSpecifier); -
4718 -
4719 if (lineEmulation) { -
4720 // ### -
4721// if (lineEmulation == QPaintEngine::PrimitiveTransform -
4722// && d->state->matrix.type() == QTransform::TxTranslate) { -
4723// } else { -
4724 QPainterPath polylinePath(points[0]); -
4725 for (int i=1; i<pointCount; ++i) -
4726 polylinePath.lineTo(points[i]); -
4727 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw); -
4728// } -
4729 } else { -
4730 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode); -
4731 } -
4732} -
4733 -
4734/*! -
4735 \overload -
4736 -
4737 Draws the polyline defined by the first \a pointCount points in \a -
4738 points using the current pen. -
4739 */ -
4740void QPainter::drawPolyline(const QPoint *points, int pointCount) -
4741{ -
4742#ifdef QT_DEBUG_DRAW -
4743 if (qt_show_painter_debug_output) -
4744 printf("QPainter::drawPolyline(), count=%d\n", pointCount); -
4745#endif -
4746 Q_D(QPainter); -
4747 -
4748 if (!d->engine || pointCount < 2) -
4749 return; -
4750 -
4751 if (d->extended) { -
4752 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode); -
4753 return; -
4754 } -
4755 -
4756 d->updateState(d->state); -
4757 -
4758 uint lineEmulation = line_emulation(d->state->emulationSpecifier); -
4759 -
4760 if (lineEmulation) { -
4761 // ### -
4762// if (lineEmulation == QPaintEngine::PrimitiveTransform -
4763// && d->state->matrix.type() == QTransform::TxTranslate) { -
4764// } else { -
4765 QPainterPath polylinePath(points[0]); -
4766 for (int i=1; i<pointCount; ++i) -
4767 polylinePath.lineTo(points[i]); -
4768 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw); -
4769// } -
4770 } else { -
4771 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode); -
4772 } -
4773} -
4774 -
4775/*! -
4776 \fn void QPainter::drawPolyline(const QPolygonF &points) -
4777 -
4778 \overload -
4779 -
4780 Draws the polyline defined by the given \a points using the -
4781 current pen. -
4782*/ -
4783 -
4784/*! -
4785 \fn void QPainter::drawPolyline(const QPolygon &points) -
4786 -
4787 \overload -
4788 -
4789 Draws the polyline defined by the given \a points using the -
4790 current pen. -
4791*/ -
4792 -
4793/*! -
4794 Draws the polygon defined by the first \a pointCount points in the -
4795 array \a points using the current pen and brush. -
4796 -
4797 \table 100% -
4798 \row -
4799 \li \inlineimage qpainter-polygon.png -
4800 \li -
4801 \snippet code/src_gui_painting_qpainter.cpp 14 -
4802 \endtable -
4803 -
4804 The first point is implicitly connected to the last point, and the -
4805 polygon is filled with the current brush(). -
4806 -
4807 If \a fillRule is Qt::WindingFill, the polygon is filled using the -
4808 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the -
4809 polygon is filled using the odd-even fill algorithm. See -
4810 \l{Qt::FillRule} for a more detailed description of these fill -
4811 rules. -
4812 -
4813 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System} -
4814*/ -
4815void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule) -
4816{ -
4817#ifdef QT_DEBUG_DRAW -
4818 if (qt_show_painter_debug_output) -
4819 printf("QPainter::drawPolygon(), count=%d\n", pointCount); -
4820#endif -
4821 -
4822 Q_D(QPainter); -
4823 -
4824 if (!d->engine || pointCount < 2) -
4825 return; -
4826 -
4827 if (d->extended) { -
4828 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule)); -
4829 return; -
4830 } -
4831 -
4832 d->updateState(d->state); -
4833 -
4834 uint emulationSpecifier = d->state->emulationSpecifier; -
4835 -
4836 if (emulationSpecifier) { -
4837 QPainterPath polygonPath(points[0]); -
4838 for (int i=1; i<pointCount; ++i) -
4839 polygonPath.lineTo(points[i]); -
4840 polygonPath.closeSubpath(); -
4841 polygonPath.setFillRule(fillRule); -
4842 d->draw_helper(polygonPath); -
4843 return; -
4844 } -
4845 -
4846 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule)); -
4847} -
4848 -
4849/*! \overload -
4850 -
4851 Draws the polygon defined by the first \a pointCount points in the -
4852 array \a points. -
4853*/ -
4854void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule) -
4855{ -
4856#ifdef QT_DEBUG_DRAW -
4857 if (qt_show_painter_debug_output) -
4858 printf("QPainter::drawPolygon(), count=%d\n", pointCount); -
4859#endif -
4860 -
4861 Q_D(QPainter); -
4862 -
4863 if (!d->engine || pointCount < 2) -
4864 return; -
4865 -
4866 if (d->extended) { -
4867 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule)); -
4868 return; -
4869 } -
4870 -
4871 d->updateState(d->state); -
4872 -
4873 uint emulationSpecifier = d->state->emulationSpecifier; -
4874 -
4875 if (emulationSpecifier) { -
4876 QPainterPath polygonPath(points[0]); -
4877 for (int i=1; i<pointCount; ++i) -
4878 polygonPath.lineTo(points[i]); -
4879 polygonPath.closeSubpath(); -
4880 polygonPath.setFillRule(fillRule); -
4881 d->draw_helper(polygonPath); -
4882 return; -
4883 } -
4884 -
4885 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule)); -
4886} -
4887 -
4888/*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule) -
4889 -
4890 \overload -
4891 -
4892 Draws the polygon defined by the given \a points using the fill -
4893 rule \a fillRule. -
4894*/ -
4895 -
4896/*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule) -
4897 -
4898 \overload -
4899 -
4900 Draws the polygon defined by the given \a points using the fill -
4901 rule \a fillRule. -
4902*/ -
4903 -
4904/*! -
4905 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount) -
4906 -
4907 Draws the convex polygon defined by the first \a pointCount points -
4908 in the array \a points using the current pen. -
4909 -
4910 \table 100% -
4911 \row -
4912 \li \inlineimage qpainter-polygon.png -
4913 \li -
4914 \snippet code/src_gui_painting_qpainter.cpp 15 -
4915 \endtable -
4916 -
4917 The first point is implicitly connected to the last point, and the -
4918 polygon is filled with the current brush(). If the supplied -
4919 polygon is not convex, i.e. it contains at least one angle larger -
4920 than 180 degrees, the results are undefined. -
4921 -
4922 On some platforms (e.g. X11), the drawConvexPolygon() function can -
4923 be faster than the drawPolygon() function. -
4924 -
4925 \sa drawPolygon(), drawPolyline(), {Coordinate System} -
4926*/ -
4927 -
4928/*! -
4929 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount) -
4930 \overload -
4931 -
4932 Draws the convex polygon defined by the first \a pointCount points -
4933 in the array \a points using the current pen. -
4934*/ -
4935 -
4936/*! -
4937 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon) -
4938 -
4939 \overload -
4940 -
4941 Draws the convex polygon defined by \a polygon using the current -
4942 pen and brush. -
4943*/ -
4944 -
4945/*! -
4946 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon) -
4947 \overload -
4948 -
4949 Draws the convex polygon defined by \a polygon using the current -
4950 pen and brush. -
4951*/ -
4952 -
4953void QPainter::drawConvexPolygon(const QPoint *points, int pointCount) -
4954{ -
4955#ifdef QT_DEBUG_DRAW -
4956 if (qt_show_painter_debug_output) -
4957 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount); -
4958#endif -
4959 -
4960 Q_D(QPainter); -
4961 -
4962 if (!d->engine || pointCount < 2) -
4963 return; -
4964 -
4965 if (d->extended) { -
4966 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode); -
4967 return; -
4968 } -
4969 -
4970 d->updateState(d->state); -
4971 -
4972 uint emulationSpecifier = d->state->emulationSpecifier; -
4973 -
4974 if (emulationSpecifier) { -
4975 QPainterPath polygonPath(points[0]); -
4976 for (int i=1; i<pointCount; ++i) -
4977 polygonPath.lineTo(points[i]); -
4978 polygonPath.closeSubpath(); -
4979 polygonPath.setFillRule(Qt::WindingFill); -
4980 d->draw_helper(polygonPath); -
4981 return; -
4982 } -
4983 -
4984 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode); -
4985} -
4986 -
4987void QPainter::drawConvexPolygon(const QPointF *points, int pointCount) -
4988{ -
4989#ifdef QT_DEBUG_DRAW -
4990 if (qt_show_painter_debug_output) -
4991 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount); -
4992#endif -
4993 -
4994 Q_D(QPainter); -
4995 -
4996 if (!d->engine || pointCount < 2) -
4997 return; -
4998 -
4999 if (d->extended) { -
5000 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode); -
5001 return; -
5002 } -
5003 -
5004 d->updateState(d->state); -
5005 -
5006 uint emulationSpecifier = d->state->emulationSpecifier; -
5007 -
5008 if (emulationSpecifier) { -
5009 QPainterPath polygonPath(points[0]); -
5010 for (int i=1; i<pointCount; ++i) -
5011 polygonPath.lineTo(points[i]); -
5012 polygonPath.closeSubpath(); -
5013 polygonPath.setFillRule(Qt::WindingFill); -
5014 d->draw_helper(polygonPath); -
5015 return; -
5016 } -
5017 -
5018 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode); -
5019} -
5020 -
5021static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m) -
5022{ -
5023 return m.inverted().map(QPointF(m.map(p).toPoint())); -
5024} -
5025 -
5026/*! -
5027 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source) -
5028 -
5029 Draws the rectangular portion \a source of the given \a pixmap -
5030 into the given \a target in the paint device. -
5031 -
5032 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree. -
5033 -
5034 \table 100% -
5035 \row -
5036 \li -
5037 \snippet code/src_gui_painting_qpainter.cpp 16 -
5038 \endtable -
5039 -
5040 If \a pixmap is a QBitmap it is drawn with the bits that are "set" -
5041 using the pens color. If backgroundMode is Qt::OpaqueMode, the -
5042 "unset" bits are drawn using the color of the background brush; if -
5043 backgroundMode is Qt::TransparentMode, the "unset" bits are -
5044 transparent. Drawing bitmaps with gradient or texture colors is -
5045 not supported. -
5046 -
5047 \sa drawImage() -
5048*/ -
5049void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) -
5050{ -
5051#if defined QT_DEBUG_DRAW -
5052 if (qt_show_painter_debug_output) -
5053 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n", -
5054 p.x(), p.y(), -
5055 pm.width(), pm.height()); -
5056#endif -
5057 -
5058 Q_D(QPainter); -
5059 -
5060 if (!d->engine || pm.isNull()) -
5061 return; -
5062 -
5063#ifndef QT_NO_DEBUG -
5064 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true); -
5065#endif -
5066 -
5067 if (d->extended) { -
5068 d->extended->drawPixmap(p, pm); -
5069 return; -
5070 } -
5071 -
5072 qreal x = p.x(); -
5073 qreal y = p.y(); -
5074 -
5075 int w = pm.width(); -
5076 int h = pm.height(); -
5077 -
5078 if (w <= 0) -
5079 return; -
5080 -
5081 // Emulate opaque background for bitmaps -
5082 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) { -
5083 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color()); -
5084 } -
5085 -
5086 d->updateState(d->state); -
5087 -
5088 if ((d->state->matrix.type() > QTransform::TxTranslate -
5089 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) -
5090 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform)) -
5091 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))) -
5092 { -
5093 save(); -
5094 // If there is no rotation involved we have to make sure we use the -
5095 // antialiased and not the aliased coordinate system by rounding the coordinates. -
5096 if (d->state->matrix.type() <= QTransform::TxScale) { -
5097 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); -
5098 x = p.x(); -
5099 y = p.y(); -
5100 } -
5101 translate(x, y); -
5102 setBackgroundMode(Qt::TransparentMode); -
5103 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform); -
5104 QBrush brush(d->state->pen.color(), pm); -
5105 setBrush(brush); -
5106 setPen(Qt::NoPen); -
5107 setBrushOrigin(QPointF(0, 0)); -
5108 -
5109 drawRect(pm.rect()); -
5110 restore(); -
5111 } else { -
5112 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) { -
5113 x += d->state->matrix.dx(); -
5114 y += d->state->matrix.dy(); -
5115 } -
5116 int scale = pm.devicePixelRatio(); -
5117 d->engine->drawPixmap(QRectF(x, y, w / scale, h / scale), pm, QRectF(0, 0, w, h)); -
5118 } -
5119} -
5120 -
5121void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -
5122{ -
5123#if defined QT_DEBUG_DRAW -
5124 if (qt_show_painter_debug_output) -
5125 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n", -
5126 r.x(), r.y(), r.width(), r.height(), -
5127 pm.width(), pm.height(), -
5128 sr.x(), sr.y(), sr.width(), sr.height()); -
5129#endif -
5130 -
5131 Q_D(QPainter); -
5132 if (!d->engine || pm.isNull()) -
5133 return; -
5134#ifndef QT_NO_DEBUG -
5135 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true); -
5136#endif -
5137 -
5138 qreal x = r.x(); -
5139 qreal y = r.y(); -
5140 qreal w = r.width(); -
5141 qreal h = r.height(); -
5142 qreal sx = sr.x(); -
5143 qreal sy = sr.y(); -
5144 qreal sw = sr.width(); -
5145 qreal sh = sr.height(); -
5146 -
5147 // Get pixmap scale. Use it when calculating the target -
5148 // rect size from pixmap size. For example, a 2X 64x64 pixel -
5149 // pixmap should result in a 32x32 point target rect. -
5150 const qreal pmscale = pm.devicePixelRatio(); -
5151 -
5152 // Sanity-check clipping -
5153 if (sw <= 0) -
5154 sw = pm.width() - sx; -
5155 -
5156 if (sh <= 0) -
5157 sh = pm.height() - sy; -
5158 -
5159 if (w < 0) -
5160 w = sw / pmscale; -
5161 if (h < 0) -
5162 h = sh / pmscale; -
5163 -
5164 if (sx < 0) { -
5165 qreal w_ratio = sx * w/sw; -
5166 x -= w_ratio; -
5167 w += w_ratio; -
5168 sw += sx; -
5169 sx = 0; -
5170 } -
5171 -
5172 if (sy < 0) { -
5173 qreal h_ratio = sy * h/sh; -
5174 y -= h_ratio; -
5175 h += h_ratio; -
5176 sh += sy; -
5177 sy = 0; -
5178 } -
5179 -
5180 if (sw + sx > pm.width()) { -
5181 qreal delta = sw - (pm.width() - sx); -
5182 qreal w_ratio = delta * w/sw; -
5183 sw -= delta; -
5184 w -= w_ratio; -
5185 } -
5186 -
5187 if (sh + sy > pm.height()) { -
5188 qreal delta = sh - (pm.height() - sy); -
5189 qreal h_ratio = delta * h/sh; -
5190 sh -= delta; -
5191 h -= h_ratio; -
5192 } -
5193 -
5194 if (w == 0 || h == 0 || sw <= 0 || sh <= 0) -
5195 return; -
5196 -
5197 if (d->extended) { -
5198 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh)); -
5199 return; -
5200 } -
5201 -
5202 // Emulate opaque background for bitmaps -
5203 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) -
5204 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color()); -
5205 -
5206 d->updateState(d->state); -
5207 -
5208 if ((d->state->matrix.type() > QTransform::TxTranslate -
5209 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) -
5210 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform)) -
5211 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)) -
5212 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform))) -
5213 { -
5214 save(); -
5215 // If there is no rotation involved we have to make sure we use the -
5216 // antialiased and not the aliased coordinate system by rounding the coordinates. -
5217 if (d->state->matrix.type() <= QTransform::TxScale) { -
5218 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); -
5219 x = p.x(); -
5220 y = p.y(); -
5221 } -
5222 -
5223 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) { -
5224 sx = qRound(sx); -
5225 sy = qRound(sy); -
5226 sw = qRound(sw); -
5227 sh = qRound(sh); -
5228 } -
5229 -
5230 translate(x, y); -
5231 scale(w / sw, h / sh); -
5232 setBackgroundMode(Qt::TransparentMode); -
5233 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform); -
5234 QBrush brush; -
5235 -
5236 if (sw == pm.width() && sh == pm.height()) -
5237 brush = QBrush(d->state->pen.color(), pm); -
5238 else -
5239 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh)); -
5240 -
5241 setBrush(brush); -
5242 setPen(Qt::NoPen); -
5243 -
5244 drawRect(QRectF(0, 0, sw, sh)); -
5245 restore(); -
5246 } else { -
5247 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) { -
5248 x += d->state->matrix.dx(); -
5249 y += d->state->matrix.dy(); -
5250 } -
5251 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh)); -
5252 } -
5253} -
5254 -
5255 -
5256/*! -
5257 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap, -
5258 const QRect &source) -
5259 \overload -
5260 -
5261 Draws the rectangular portion \a source of the given \a pixmap -
5262 into the given \a target in the paint device. -
5263 -
5264 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree. -
5265*/ -
5266 -
5267/*! -
5268 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap, -
5269 const QRectF &source) -
5270 \overload -
5271 -
5272 Draws the rectangular portion \a source of the given \a pixmap -
5273 with its origin at the given \a point. -
5274*/ -
5275 -
5276/*! -
5277 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap, -
5278 const QRect &source) -
5279 -
5280 \overload -
5281 -
5282 Draws the rectangular portion \a source of the given \a pixmap -
5283 with its origin at the given \a point. -
5284*/ -
5285 -
5286/*! -
5287 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap) -
5288 \overload -
5289 -
5290 Draws the given \a pixmap with its origin at the given \a point. -
5291*/ -
5292 -
5293/*! -
5294 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap) -
5295 \overload -
5296 -
5297 Draws the given \a pixmap with its origin at the given \a point. -
5298*/ -
5299 -
5300/*! -
5301 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap) -
5302 -
5303 \overload -
5304 -
5305 Draws the given \a pixmap at position (\a{x}, \a{y}). -
5306*/ -
5307 -
5308/*! -
5309 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap) -
5310 \overload -
5311 -
5312 Draws the given \a pixmap into the given \a rectangle. -
5313 -
5314 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree. -
5315*/ -
5316 -
5317/*! -
5318 \fn void QPainter::drawPixmap(int x, int y, int width, int height, -
5319 const QPixmap &pixmap) -
5320 -
5321 \overload -
5322 -
5323 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y}) -
5324 with the given \a width and \a height. -
5325*/ -
5326 -
5327/*! -
5328 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap, -
5329 int sx, int sy, int sw, int sh) -
5330 -
5331 \overload -
5332 -
5333 Draws the rectangular portion with the origin (\a{sx}, \a{sy}), -
5334 width \a sw and height \a sh, of the given \a pixmap , at the -
5335 point (\a{x}, \a{y}), with a width of \a w and a height of \a h. -
5336 If sw or sh are equal to zero the width/height of the pixmap -
5337 is used and adjusted by the offset sx/sy; -
5338*/ -
5339 -
5340/*! -
5341 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap, -
5342 int sx, int sy, int sw, int sh) -
5343 -
5344 \overload -
5345 -
5346 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a -
5347 pixmap into the paint device. -
5348 -
5349 (\a{x}, \a{y}) specifies the top-left point in the paint device that is -
5350 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a -
5351 pixmap that is to be drawn. The default is (0, 0). -
5352 -
5353 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn. -
5354 The default, (0, 0) (and negative) means all the way to the -
5355 bottom-right of the pixmap. -
5356*/ -
5357 -
5358void QPainter::drawImage(const QPointF &p, const QImage &image) -
5359{ -
5360 Q_D(QPainter); -
5361 -
5362 if (!d->engine || image.isNull()) -
5363 return; -
5364 -
5365 if (d->extended) { -
5366 d->extended->drawImage(p, image); -
5367 return; -
5368 } -
5369 -
5370 qreal x = p.x(); -
5371 qreal y = p.y(); -
5372 -
5373 int w = image.width(); -
5374 int h = image.height(); -
5375 qreal scale = image.devicePixelRatio(); -
5376 -
5377 d->updateState(d->state); -
5378 -
5379 if (((d->state->matrix.type() > QTransform::TxTranslate) -
5380 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) -
5381 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform)) -
5382 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))) -
5383 { -
5384 save(); -
5385 // If there is no rotation involved we have to make sure we use the -
5386 // antialiased and not the aliased coordinate system by rounding the coordinates. -
5387 if (d->state->matrix.type() <= QTransform::TxScale) { -
5388 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); -
5389 x = p.x(); -
5390 y = p.y(); -
5391 } -
5392 translate(x, y); -
5393 setBackgroundMode(Qt::TransparentMode); -
5394 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform); -
5395 QBrush brush(image); -
5396 setBrush(brush); -
5397 setPen(Qt::NoPen); -
5398 setBrushOrigin(QPointF(0, 0)); -
5399 drawRect(QRect(QPoint(0, 0), image.size() / scale)); -
5400 restore(); -
5401 return; -
5402 } -
5403 -
5404 if (d->state->matrix.type() == QTransform::TxTranslate -
5405 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) { -
5406 x += d->state->matrix.dx(); -
5407 y += d->state->matrix.dy(); -
5408 } -
5409 -
5410 d->engine->drawImage(QRectF(x, y, w / scale, h / scale), image, QRectF(0, 0, w, h), Qt::AutoColor); -
5411} -
5412 -
5413void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, -
5414 Qt::ImageConversionFlags flags) -
5415{ -
5416 Q_D(QPainter); -
5417 -
5418 if (!d->engine || image.isNull()) -
5419 return; -
5420 -
5421 qreal x = targetRect.x(); -
5422 qreal y = targetRect.y(); -
5423 qreal w = targetRect.width(); -
5424 qreal h = targetRect.height(); -
5425 qreal sx = sourceRect.x(); -
5426 qreal sy = sourceRect.y(); -
5427 qreal sw = sourceRect.width(); -
5428 qreal sh = sourceRect.height(); -
5429 qreal imageScale = image.devicePixelRatio(); -
5430 -
5431 // Sanity-check clipping -
5432 if (sw <= 0) -
5433 sw = image.width() - sx; -
5434 -
5435 if (sh <= 0) -
5436 sh = image.height() - sy; -
5437 -
5438 if (w < 0) -
5439 w = sw / imageScale; -
5440 if (h < 0) -
5441 h = sh / imageScale; -
5442 -
5443 if (sx < 0) { -
5444 qreal w_ratio = sx * w/sw; -
5445 x -= w_ratio; -
5446 w += w_ratio; -
5447 sw += sx; -
5448 sx = 0; -
5449 } -
5450 -
5451 if (sy < 0) { -
5452 qreal h_ratio = sy * h/sh; -
5453 y -= h_ratio; -
5454 h += h_ratio; -
5455 sh += sy; -
5456 sy = 0; -
5457 } -
5458 -
5459 if (sw + sx > image.width()) { -
5460 qreal delta = sw - (image.width() - sx); -
5461 qreal w_ratio = delta * w/sw; -
5462 sw -= delta; -
5463 w -= w_ratio; -
5464 } -
5465 -
5466 if (sh + sy > image.height()) { -
5467 qreal delta = sh - (image.height() - sy); -
5468 qreal h_ratio = delta * h/sh; -
5469 sh -= delta; -
5470 h -= h_ratio; -
5471 } -
5472 -
5473 if (w == 0 || h == 0 || sw <= 0 || sh <= 0) -
5474 return; -
5475 -
5476 if (d->extended) { -
5477 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags); -
5478 return; -
5479 } -
5480 -
5481 d->updateState(d->state); -
5482 -
5483 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h)) -
5484 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) -
5485 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform)) -
5486 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))) -
5487 { -
5488 save(); -
5489 // If there is no rotation involved we have to make sure we use the -
5490 // antialiased and not the aliased coordinate system by rounding the coordinates. -
5491 if (d->state->matrix.type() <= QTransform::TxScale) { -
5492 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); -
5493 x = p.x(); -
5494 y = p.y(); -
5495 } -
5496 -
5497 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) { -
5498 sx = qRound(sx); -
5499 sy = qRound(sy); -
5500 sw = qRound(sw); -
5501 sh = qRound(sh); -
5502 } -
5503 translate(x, y); -
5504 scale(w / sw, h / sh); -
5505 setBackgroundMode(Qt::TransparentMode); -
5506 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform); -
5507 QBrush brush(image); -
5508 setBrush(brush); -
5509 setPen(Qt::NoPen); -
5510 setBrushOrigin(QPointF(-sx, -sy)); -
5511 -
5512 drawRect(QRectF(0, 0, sw, sh)); -
5513 restore(); -
5514 return; -
5515 } -
5516 -
5517 if (d->state->matrix.type() == QTransform::TxTranslate -
5518 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) { -
5519 x += d->state->matrix.dx(); -
5520 y += d->state->matrix.dy(); -
5521 } -
5522 -
5523 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags); -
5524} -
5525 -
5526/*! -
5527 \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs) -
5528 -
5529 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the -
5530 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font -
5531 selected on \a glyphs and at offsets given by the positions in \a glyphs. -
5532 -
5533 \since 4.8 -
5534 -
5535 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes() -
5536*/ -
5537#if !defined(QT_NO_RAWFONT) -
5538void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun) -
5539{ -
5540 Q_D(QPainter); -
5541 -
5542 QRawFont font = glyphRun.rawFont(); -
5543 if (!font.isValid()) -
5544 return; -
5545 -
5546 QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun); -
5547 -
5548 const quint32 *glyphIndexes = glyphRun_d->glyphIndexData; -
5549 const QPointF *glyphPositions = glyphRun_d->glyphPositionData; -
5550 -
5551 int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize); -
5552 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count); -
5553 -
5554 QRawFontPrivate *fontD = QRawFontPrivate::get(font); -
5555 bool supportsTransformations = d->extended -
5556 ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix) -
5557 : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine(); -
5558 -
5559 for (int i=0; i<count; ++i) { -
5560 QPointF processedPosition = position + glyphPositions[i]; -
5561 if (!supportsTransformations) -
5562 processedPosition = d->state->transform().map(processedPosition); -
5563 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition); -
5564 } -
5565 -
5566 d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(), -
5567 glyphRun.underline(), glyphRun.strikeOut()); -
5568} -
5569 -
5570void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions, -
5571 int glyphCount, -
5572 const QRawFont &font, bool overline, bool underline, -
5573 bool strikeOut) -
5574{ -
5575 Q_Q(QPainter); -
5576 -
5577 updateState(state); -
5578 -
5579 QRawFontPrivate *fontD = QRawFontPrivate::get(font); -
5580 QFontEngine *fontEngine = fontD->fontEngine; -
5581 -
5582 QFixed leftMost; -
5583 QFixed rightMost; -
5584 QFixed baseLine; -
5585 for (int i=0; i<glyphCount; ++i) { -
5586 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); -
5587 if (i == 0 || leftMost > positions[i].x) -
5588 leftMost = positions[i].x; -
5589 -
5590 // We don't support glyphs that do not share a common baseline. If this turns out to -
5591 // be a relevant use case, then we need to find clusters of glyphs that share a baseline -
5592 // and do a drawTextItemDecorations call per cluster. -
5593 if (i == 0 || baseLine < positions[i].y) -
5594 baseLine = positions[i].y; -
5595 -
5596 // We use the advance rather than the actual bounds to match the algorithm in drawText() -
5597 if (i == 0 || rightMost < positions[i].x + gm.xoff) -
5598 rightMost = positions[i].x + gm.xoff; -
5599 } -
5600 -
5601 QFixed width = rightMost - leftMost; -
5602 -
5603 if (extended != 0 && state->matrix.isAffine()) { -
5604 QStaticTextItem staticTextItem; -
5605 staticTextItem.color = state->pen.color(); -
5606 staticTextItem.font = state->font; -
5607 staticTextItem.setFontEngine(fontEngine); -
5608 staticTextItem.numGlyphs = glyphCount; -
5609 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray)); -
5610 staticTextItem.glyphPositions = positions; -
5611 -
5612 extended->drawStaticTextItem(&staticTextItem); -
5613 } else { -
5614 QTextItemInt textItem; -
5615 textItem.fontEngine = fontEngine; -
5616 -
5617 QVarLengthArray<QFixed, 128> advances(glyphCount); -
5618 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount); -
5619 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount); -
5620 memset(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes)); -
5621 memset(advances.data(), 0, advances.size() * sizeof(QFixed)); -
5622 memset(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification)); -
5623 -
5624 textItem.glyphs.numGlyphs = glyphCount; -
5625 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray)); -
5626 textItem.glyphs.offsets = positions; -
5627 textItem.glyphs.advances_x = advances.data(); -
5628 textItem.glyphs.advances_y = advances.data(); -
5629 textItem.glyphs.justifications = glyphJustifications.data(); -
5630 textItem.glyphs.attributes = glyphAttributes.data(); -
5631 -
5632 engine->drawTextItem(QPointF(0, 0), textItem); -
5633 } -
5634 -
5635 QTextItemInt::RenderFlags flags; -
5636 if (underline) -
5637 flags |= QTextItemInt::Underline; -
5638 if (overline) -
5639 flags |= QTextItemInt::Overline; -
5640 if (strikeOut) -
5641 flags |= QTextItemInt::StrikeOut; -
5642 -
5643 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()), -
5644 fontEngine, -
5645 0, // textEngine -
5646 (underline -
5647 ? QTextCharFormat::SingleUnderline -
5648 : QTextCharFormat::NoUnderline), -
5649 flags, width.toReal(), QTextCharFormat()); -
5650} -
5651#endif // QT_NO_RAWFONT -
5652 -
5653/*! -
5654 -
5655 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText) -
5656 \since 4.7 -
5657 \overload -
5658 -
5659 Draws the \a staticText at the \a topLeftPosition. -
5660 -
5661 \note The y-position is used as the top of the font. -
5662 -
5663*/ -
5664 -
5665/*! -
5666 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText) -
5667 \since 4.7 -
5668 \overload -
5669 -
5670 Draws the \a staticText at coordinates \a left and \a top. -
5671 -
5672 \note The y-position is used as the top of the font. -
5673*/ -
5674 -
5675/*! -
5676 \fn void QPainter::drawText(const QPointF &position, const QString &text) -
5677 -
5678 Draws the given \a text with the currently defined text direction, -
5679 beginning at the given \a position. -
5680 -
5681 This function does not handle the newline character (\\n), as it cannot -
5682 break text into multiple lines, and it cannot display the newline character. -
5683 Use the QPainter::drawText() overload that takes a rectangle instead -
5684 if you want to draw multiple lines of text with the newline character, or -
5685 if you want the text to be wrapped. -
5686 -
5687 By default, QPainter draws text anti-aliased. -
5688 -
5689 \note The y-position is used as the baseline of the font. -
5690 -
5691 \sa setFont(), setPen() -
5692*/ -
5693 -
5694void QPainter::drawText(const QPointF &p, const QString &str) -
5695{ -
5696 drawText(p, str, 0, 0); -
5697} -
5698 -
5699/*! -
5700 \since 4.7 -
5701 -
5702 Draws the given \a staticText at the given \a topLeftPosition. -
5703 -
5704 The text will be drawn using the font and the transformation set on the painter. If the -
5705 font and/or transformation set on the painter are different from the ones used to initialize -
5706 the layout of the QStaticText, then the layout will have to be recalculated. Use -
5707 QStaticText::prepare() to initialize \a staticText with the font and transformation with which -
5708 it will later be drawn. -
5709 -
5710 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was -
5711 last drawn, then there will be a slight overhead when translating the text to its new position. -
5712 -
5713 \note If the painter's transformation is not affine, then \a staticText will be drawn using -
5714 regular calls to drawText(), losing any potential for performance improvement. -
5715 -
5716 \note The y-position is used as the top of the font. -
5717 -
5718 \sa QStaticText -
5719*/ -
5720void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText) -
5721{ -
5722 Q_D(QPainter); -
5723 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen) -
5724 return; -
5725 -
5726 QStaticTextPrivate *staticText_d = -
5727 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText)); -
5728 -
5729 if (font() != staticText_d->font) { -
5730 staticText_d->font = font(); -
5731 staticText_d->needsRelayout = true; -
5732 } -
5733 -
5734 // If we don't have an extended paint engine, or if the painter is projected, -
5735 // we go through standard code path -
5736 if (d->extended == 0 || !d->state->matrix.isAffine()) { -
5737 staticText_d->paintText(topLeftPosition, this); -
5738 return; -
5739 } -
5740 -
5741 QFontEngine *fe = staticText_d->font.d->engineForScript(QUnicodeTables::Common); -
5742 if (fe->type() == QFontEngine::Multi) -
5743 fe = static_cast<QFontEngineMulti *>(fe)->engine(0); -
5744 bool supportsTransformations = d->extended->supportsTransformations(fe, -
5745 d->state->matrix); -
5746 if (supportsTransformations && !staticText_d->untransformedCoordinates) { -
5747 staticText_d->untransformedCoordinates = true; -
5748 staticText_d->needsRelayout = true; -
5749 } else if (!supportsTransformations && staticText_d->untransformedCoordinates) { -
5750 staticText_d->untransformedCoordinates = false; -
5751 staticText_d->needsRelayout = true; -
5752 } -
5753 -
5754 // Don't recalculate entire layout because of translation, rather add the dx and dy -
5755 // into the position to move each text item the correct distance. -
5756 QPointF transformedPosition = topLeftPosition; -
5757 if (!staticText_d->untransformedCoordinates) -
5758 transformedPosition = transformedPosition * d->state->matrix; -
5759 QTransform oldMatrix; -
5760 -
5761 // The translation has been applied to transformedPosition. Remove translation -
5762 // component from matrix. -
5763 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) { -
5764 qreal m11 = d->state->matrix.m11(); -
5765 qreal m12 = d->state->matrix.m12(); -
5766 qreal m13 = d->state->matrix.m13(); -
5767 qreal m21 = d->state->matrix.m21(); -
5768 qreal m22 = d->state->matrix.m22(); -
5769 qreal m23 = d->state->matrix.m23(); -
5770 qreal m33 = d->state->matrix.m33(); -
5771 -
5772 oldMatrix = d->state->matrix; -
5773 d->state->matrix.setMatrix(m11, m12, m13, -
5774 m21, m22, m23, -
5775 0.0, 0.0, m33); -
5776 } -
5777 -
5778 // If the transform is not identical to the text transform, -
5779 // we have to relayout the text (for other transformations than plain translation) -
5780 bool staticTextNeedsReinit = staticText_d->needsRelayout; -
5781 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) { -
5782 staticText_d->matrix = d->state->matrix; -
5783 staticTextNeedsReinit = true; -
5784 } -
5785 -
5786 // Recreate the layout of the static text because the matrix or font has changed -
5787 if (staticTextNeedsReinit) -
5788 staticText_d->init(); -
5789 -
5790 if (transformedPosition != staticText_d->position) { // Translate to actual position -
5791 QFixed fx = QFixed::fromReal(transformedPosition.x()); -
5792 QFixed fy = QFixed::fromReal(transformedPosition.y()); -
5793 QFixed oldX = QFixed::fromReal(staticText_d->position.x()); -
5794 QFixed oldY = QFixed::fromReal(staticText_d->position.y()); -
5795 for (int item=0; item<staticText_d->itemCount;++item) { -
5796 QStaticTextItem *textItem = staticText_d->items + item; -
5797 for (int i=0; i<textItem->numGlyphs; ++i) { -
5798 textItem->glyphPositions[i].x += fx - oldX; -
5799 textItem->glyphPositions[i].y += fy - oldY; -
5800 } -
5801 textItem->userDataNeedsUpdate = true; -
5802 } -
5803 -
5804 staticText_d->position = transformedPosition; -
5805 } -
5806 -
5807 QPen oldPen = d->state->pen; -
5808 QColor currentColor = oldPen.color(); -
5809 for (int i=0; i<staticText_d->itemCount; ++i) { -
5810 QStaticTextItem *item = staticText_d->items + i; -
5811 if (item->color.isValid() && currentColor != item->color) { -
5812 setPen(item->color); -
5813 currentColor = item->color; -
5814 } -
5815 d->extended->drawStaticTextItem(item); -
5816 -
5817 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions, -
5818 item->numGlyphs, item->fontEngine(), staticText_d->font, -
5819 QTextCharFormat()); -
5820 } -
5821 if (currentColor != oldPen.color()) -
5822 setPen(oldPen); -
5823 -
5824 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating()) -
5825 d->state->matrix = oldMatrix; -
5826} -
5827 -
5828/*! -
5829 \internal -
5830*/ -
5831void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding) -
5832{ -
5833#ifdef QT_DEBUG_DRAW -
5834 if (qt_show_painter_debug_output) -
5835 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData()); -
5836#endif -
5837 -
5838 Q_D(QPainter); -
5839 -
5840 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen) -
5841 return; -
5842 -
5843 if (tf & Qt::TextBypassShaping) { -
5844 // Skip harfbuzz complex shaping, shape using glyph advances only -
5845 int len = str.length(); -
5846 int numGlyphs = len; -
5847 QVarLengthGlyphLayoutArray glyphs(len); -
5848 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common); -
5849 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) { -
5850 glyphs.resize(numGlyphs); -
5851 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) -
5852 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice"); -
5853 } -
5854 -
5855 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine); -
5856 drawTextItem(p, gf); -
5857 return; -
5858 } -
5859 -
5860 QStackTextEngine engine(str, d->state->font); -
5861 engine.option.setTextDirection(d->state->layoutDirection); -
5862 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) { -
5863 engine.ignoreBidi = true; -
5864 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft); -
5865 } -
5866 engine.itemize(); -
5867 QScriptLine line; -
5868 line.length = str.length(); -
5869 engine.shapeLine(line); -
5870 -
5871 int nItems = engine.layoutData->items.size(); -
5872 QVarLengthArray<int> visualOrder(nItems); -
5873 QVarLengthArray<uchar> levels(nItems); -
5874 for (int i = 0; i < nItems; ++i) -
5875 levels[i] = engine.layoutData->items[i].analysis.bidiLevel; -
5876 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data()); -
5877 -
5878 if (justificationPadding > 0) { -
5879 engine.option.setAlignment(Qt::AlignJustify); -
5880 engine.forceJustification = true; -
5881 // this works because justify() is only interested in the difference between width and textWidth -
5882 line.width = justificationPadding; -
5883 engine.justify(line); -
5884 } -
5885 QFixed x = QFixed::fromReal(p.x()); -
5886 -
5887 for (int i = 0; i < nItems; ++i) { -
5888 int item = visualOrder[i]; -
5889 const QScriptItem &si = engine.layoutData->items.at(item); -
5890 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) { -
5891 x += si.width; -
5892 continue; -
5893 } -
5894 QFont f = engine.font(si); -
5895 QTextItemInt gf(si, &f); -
5896 gf.glyphs = engine.shapedGlyphs(&si); -
5897 gf.chars = engine.layoutData->string.unicode() + si.position; -
5898 gf.num_chars = engine.length(item); -
5899 if (engine.forceJustification) { -
5900 for (int j=0; j<gf.glyphs.numGlyphs; ++j) -
5901 gf.width += gf.glyphs.effectiveAdvance(j); -
5902 } else { -
5903 gf.width = si.width; -
5904 } -
5905 gf.logClusters = engine.logClusters(&si); -
5906 -
5907 drawTextItem(QPointF(x.toReal(), p.y()), gf); -
5908 -
5909 x += gf.width; -
5910 } -
5911} -
5912 -
5913void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br) -
5914{ -
5915#ifdef QT_DEBUG_DRAW -
5916 if (qt_show_painter_debug_output) -
5917 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n", -
5918 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData()); -
5919#endif -
5920 -
5921 Q_D(QPainter); -
5922 -
5923 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen) -
5924 return; -
5925 -
5926 if (!d->extended) -
5927 d->updateState(d->state); -
5928 -
5929 QRectF bounds; -
5930 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this); -
5931 if (br) -
5932 *br = bounds.toAlignedRect(); -
5933} -
5934 -
5935/*! -
5936 \fn void QPainter::drawText(const QPoint &position, const QString &text) -
5937 -
5938 \overload -
5939 -
5940 Draws the given \a text with the currently defined text direction, -
5941 beginning at the given \a position. -
5942 -
5943 By default, QPainter draws text anti-aliased. -
5944 -
5945 \note The y-position is used as the baseline of the font. -
5946 -
5947 \sa setFont(), setPen() -
5948*/ -
5949 -
5950/*! -
5951 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect) -
5952 \overload -
5953 -
5954 Draws the given \a text within the provided \a rectangle. -
5955 The \a rectangle along with alignment \a flags defines the anchors for the \a text. -
5956 -
5957 \table 100% -
5958 \row -
5959 \li \inlineimage qpainter-text.png -
5960 \li -
5961 \snippet code/src_gui_painting_qpainter.cpp 17 -
5962 \endtable -
5963 -
5964 The \a boundingRect (if not null) is set to the what the bounding rectangle -
5965 should be in order to enclose the whole text. The \a flags argument is a bitwise -
5966 OR of the following flags: -
5967 -
5968 \list -
5969 \li Qt::AlignLeft -
5970 \li Qt::AlignRight -
5971 \li Qt::AlignHCenter -
5972 \li Qt::AlignJustify -
5973 \li Qt::AlignTop -
5974 \li Qt::AlignBottom -
5975 \li Qt::AlignVCenter -
5976 \li Qt::AlignCenter -
5977 \li Qt::TextDontClip -
5978 \li Qt::TextSingleLine -
5979 \li Qt::TextExpandTabs -
5980 \li Qt::TextShowMnemonic -
5981 \li Qt::TextWordWrap -
5982 \li Qt::TextIncludeTrailingSpaces -
5983 \endlist -
5984 -
5985 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection() -
5986 -
5987 By default, QPainter draws text anti-aliased. -
5988 -
5989 \note The y-coordinate of \a rectangle is used as the top of the font. -
5990*/ -
5991void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br) -
5992{ -
5993#ifdef QT_DEBUG_DRAW -
5994 if (qt_show_painter_debug_output) -
5995 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n", -
5996 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData()); -
5997#endif -
5998 -
5999 Q_D(QPainter); -
6000 -
6001 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen) -
6002 return; -
6003 -
6004 if (!d->extended) -
6005 d->updateState(d->state); -
6006 -
6007 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this); -
6008} -
6009 -
6010/*! -
6011 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect) -
6012 \overload -
6013 -
6014 Draws the given \a text within the provided \a rectangle according -
6015 to the specified \a flags. The \a boundingRect (if not null) is set to -
6016 the what the bounding rectangle should be in order to enclose the whole text. -
6017 -
6018 By default, QPainter draws text anti-aliased. -
6019 -
6020 \note The y-coordinate of \a rectangle is used as the top of the font. -
6021 -
6022 \sa setFont(), setPen() -
6023*/ -
6024 -
6025/*! -
6026 \fn void QPainter::drawText(int x, int y, const QString &text) -
6027 -
6028 \overload -
6029 -
6030 Draws the given \a text at position (\a{x}, \a{y}), using the painter's -
6031 currently defined text direction. -
6032 -
6033 By default, QPainter draws text anti-aliased. -
6034 -
6035 \note The y-position is used as the baseline of the font. -
6036 -
6037 \sa setFont(), setPen() -
6038*/ -
6039 -
6040/*! -
6041 \fn void QPainter::drawText(int x, int y, int width, int height, int flags, -
6042 const QString &text, QRect *boundingRect) -
6043 -
6044 \overload -
6045 -
6046 Draws the given \a text within the rectangle with origin (\a{x}, -
6047 \a{y}), \a width and \a height. -
6048 -
6049 The \a boundingRect (if not null) is set to the actual bounding -
6050 rectangle of the output. The \a flags argument is a bitwise OR of -
6051 the following flags: -
6052 -
6053 \list -
6054 \li Qt::AlignLeft -
6055 \li Qt::AlignRight -
6056 \li Qt::AlignHCenter -
6057 \li Qt::AlignJustify -
6058 \li Qt::AlignTop -
6059 \li Qt::AlignBottom -
6060 \li Qt::AlignVCenter -
6061 \li Qt::AlignCenter -
6062 \li Qt::TextSingleLine -
6063 \li Qt::TextExpandTabs -
6064 \li Qt::TextShowMnemonic -
6065 \li Qt::TextWordWrap -
6066 \endlist -
6067 -
6068 By default, QPainter draws text anti-aliased. -
6069 -
6070 \note The y-position is used as the top of the font. -
6071 -
6072 \sa Qt::AlignmentFlag, Qt::TextFlag, setFont(), setPen() -
6073*/ -
6074 -
6075/*! -
6076 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text, -
6077 const QTextOption &option) -
6078 \overload -
6079 -
6080 Draws the given \a text in the \a rectangle specified using the \a option -
6081 to control its positioning and orientation. -
6082 -
6083 By default, QPainter draws text anti-aliased. -
6084 -
6085 \note The y-coordinate of \a rectangle is used as the top of the font. -
6086 -
6087 \sa setFont(), setPen() -
6088*/ -
6089void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o) -
6090{ -
6091#ifdef QT_DEBUG_DRAW -
6092 if (qt_show_painter_debug_output) -
6093 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n", -
6094 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData()); -
6095#endif -
6096 -
6097 Q_D(QPainter); -
6098 -
6099 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen) -
6100 return; -
6101 -
6102 if (!d->extended) -
6103 d->updateState(d->state); -
6104 -
6105 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this); -
6106} -
6107 -
6108/*! -
6109 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti) -
6110 -
6111 \internal -
6112 \overload -
6113*/ -
6114 -
6115/*! -
6116 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti) -
6117 -
6118 \internal -
6119 \overload -
6120 -
6121 Draws the text item \a ti at position \a p. -
6122*/ -
6123 -
6124/*! -
6125 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti) -
6126 -
6127 \internal -
6128 \since 4.1 -
6129 -
6130 Draws the text item \a ti at position \a p. -
6131 -
6132 This method ignores the painters background mode and -
6133 color. drawText and qt_format_text have to do it themselves, as -
6134 only they know the extents of the complete string. -
6135 -
6136 It ignores the font set on the painter as the text item has one of its own. -
6137 -
6138 The underline and strikeout parameters of the text items font are -
6139 ignored aswell. You'll need to pass in the correct flags to get -
6140 underlining and strikeout. -
6141*/ -
6142 -
6143static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) -
6144{ -
6145 const qreal radiusBase = qMax(qreal(1), maxRadius); -
6146 -
6147 QString key = QLatin1String("WaveUnderline-") -
6148 % pen.color().name() -
6149 % HexString<qreal>(radiusBase); -
6150 -
6151 QPixmap pixmap; -
6152 if (QPixmapCache::find(key, pixmap)) -
6153 return pixmap; -
6154 -
6155 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio -
6156 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod); -
6157 const int radius = qFloor(radiusBase); -
6158 -
6159 QPainterPath path; -
6160 -
6161 qreal xs = 0; -
6162 qreal ys = radius; -
6163 -
6164 while (xs < width) { -
6165 xs += halfPeriod; -
6166 ys = -ys; -
6167 path.quadTo(xs - halfPeriod / 2, ys, xs, 0); -
6168 } -
6169 -
6170 pixmap = QPixmap(width, radius * 2); -
6171 pixmap.fill(Qt::transparent); -
6172 { -
6173 QPen wavePen = pen; -
6174 wavePen.setCapStyle(Qt::SquareCap); -
6175 -
6176 // This is to protect against making the line too fat, as happens on Mac OS X -
6177 // due to it having a rather thick width for the regular underline. -
6178 const qreal maxPenWidth = .8 * radius; -
6179 if (wavePen.widthF() > maxPenWidth) -
6180 wavePen.setWidth(maxPenWidth); -
6181 -
6182 QPainter imgPainter(&pixmap); -
6183 imgPainter.setPen(wavePen); -
6184 imgPainter.setRenderHint(QPainter::Antialiasing); -
6185 imgPainter.translate(0, radius); -
6186 imgPainter.drawPath(path); -
6187 } -
6188 -
6189 QPixmapCache::insert(key, pixmap); -
6190 -
6191 return pixmap; -
6192} -
6193 -
6194static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine, -
6195 QTextCharFormat::UnderlineStyle underlineStyle, -
6196 QTextItem::RenderFlags flags, qreal width, -
6197 const QTextCharFormat &charFormat) -
6198{ -
6199 if (underlineStyle == QTextCharFormat::NoUnderline -
6200 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline))) -
6201 return; -
6202 -
6203 const QPen oldPen = painter->pen(); -
6204 const QBrush oldBrush = painter->brush(); -
6205 painter->setBrush(Qt::NoBrush); -
6206 QPen pen = oldPen; -
6207 pen.setStyle(Qt::SolidLine); -
6208 pen.setWidthF(fe->lineThickness().toReal()); -
6209 pen.setCapStyle(Qt::FlatCap); -
6210 -
6211 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y()); -
6212 -
6213 bool wasCompatiblePainting = painter->renderHints() -
6214 & QPainter::Qt4CompatiblePainting; -
6215 -
6216 if (wasCompatiblePainting) -
6217 painter->setRenderHint(QPainter::Qt4CompatiblePainting, false); -
6218 -
6219 const qreal underlineOffset = fe->underlinePosition().toReal(); -
6220 // deliberately ceil the offset to avoid the underline coming too close to -
6221 // the text above it. -
6222 const qreal underlinePos = pos.y() + qCeil(underlineOffset) + 0.5; -
6223 -
6224 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) { -
6225 QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); -
6226 if (theme) -
6227 underlineStyle = QTextCharFormat::UnderlineStyle(theme->themeHint(QPlatformTheme::SpellCheckUnderlineStyle).toInt()); -
6228 } -
6229 -
6230 if (underlineStyle == QTextCharFormat::WaveUnderline) { -
6231 painter->save(); -
6232 painter->translate(0, pos.y() + 1); -
6233 -
6234 QColor uc = charFormat.underlineColor(); -
6235 if (uc.isValid()) -
6236 pen.setColor(uc); -
6237 -
6238 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms -
6239 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen); -
6240 const int descent = (int) fe->descent().toReal(); -
6241 -
6242 painter->setBrushOrigin(painter->brushOrigin().x(), 0); -
6243 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave); -
6244 painter->restore(); -
6245 } else if (underlineStyle != QTextCharFormat::NoUnderline) { -
6246 QColor uc = charFormat.underlineColor(); -
6247 if (uc.isValid()) -
6248 pen.setColor(uc); -
6249 -
6250 pen.setStyle((Qt::PenStyle)(underlineStyle)); -
6251 painter->setPen(pen); -
6252 QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos); -
6253 if (textEngine) -
6254 textEngine->addUnderline(painter, underline); -
6255 else -
6256 painter->drawLine(underline); -
6257 } -
6258 -
6259 pen.setStyle(Qt::SolidLine); -
6260 pen.setColor(oldPen.color()); -
6261 -
6262 if (flags & QTextItem::StrikeOut) { -
6263 QLineF strikeOutLine = line; -
6264 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.); -
6265 painter->setPen(pen); -
6266 if (textEngine) -
6267 textEngine->addStrikeOut(painter, strikeOutLine); -
6268 else -
6269 painter->drawLine(strikeOutLine); -
6270 } -
6271 -
6272 if (flags & QTextItem::Overline) { -
6273 QLineF overline = line; -
6274 overline.translate(0., - fe->ascent().toReal()); -
6275 painter->setPen(pen); -
6276 if (textEngine) -
6277 textEngine->addOverline(painter, overline); -
6278 else -
6279 painter->drawLine(overline); -
6280 } -
6281 -
6282 painter->setPen(oldPen); -
6283 painter->setBrush(oldBrush); -
6284 -
6285 if (wasCompatiblePainting) -
6286 painter->setRenderHint(QPainter::Qt4CompatiblePainting); -
6287} -
6288 -
6289Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, -
6290 const QFixedPoint *positions, int glyphCount, -
6291 QFontEngine *fontEngine, const QFont &font, -
6292 const QTextCharFormat &charFormat) -
6293{ -
6294 if (!(font.underline() || font.strikeOut() || font.overline())) -
6295 return; -
6296 -
6297 QFixed leftMost; -
6298 QFixed rightMost; -
6299 QFixed baseLine; -
6300 for (int i=0; i<glyphCount; ++i) { -
6301 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); -
6302 if (i == 0 || leftMost > positions[i].x) -
6303 leftMost = positions[i].x; -
6304 -
6305 // We don't support glyphs that do not share a common baseline. If this turns out to -
6306 // be a relevant use case, then we need to find clusters of glyphs that share a baseline -
6307 // and do a drawTextItemDecoration call per cluster. -
6308 if (i == 0 || baseLine < positions[i].y) -
6309 baseLine = positions[i].y; -
6310 -
6311 // We use the advance rather than the actual bounds to match the algorithm in drawText() -
6312 if (i == 0 || rightMost < positions[i].x + gm.xoff) -
6313 rightMost = positions[i].x + gm.xoff; -
6314 } -
6315 -
6316 QFixed width = rightMost - leftMost; -
6317 QTextItem::RenderFlags flags = 0; -
6318 -
6319 if (font.underline()) -
6320 flags |= QTextItem::Underline; -
6321 if (font.overline()) -
6322 flags |= QTextItem::Overline; -
6323 if (font.strikeOut()) -
6324 flags |= QTextItem::StrikeOut; -
6325 -
6326 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()), -
6327 fontEngine, -
6328 0, // textEngine -
6329 font.underline() ? QTextCharFormat::SingleUnderline -
6330 : QTextCharFormat::NoUnderline, flags, -
6331 width.toReal(), charFormat); -
6332} -
6333 -
6334void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti) -
6335{ -
6336 Q_D(QPainter); -
6337 -
6338 d->drawTextItem(p, ti, static_cast<QTextEngine *>(0)); -
6339} -
6340 -
6341void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine) -
6342{ -
6343#ifdef QT_DEBUG_DRAW -
6344 if (qt_show_painter_debug_output) -
6345 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n", -
6346 p.x(), p.y(), qPrintable(_ti.text())); -
6347#endif -
6348 -
6349 Q_Q(QPainter); -
6350 -
6351 if (!engine) -
6352 return; -
6353 -
6354#ifndef QT_NO_DEBUG -
6355 qt_painter_thread_test(device->devType(), -
6356 "text and fonts", -
6357 QFontDatabase::supportsThreadedFontRendering()); -
6358#endif -
6359 -
6360 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti)); -
6361 -
6362 if (!extended && state->bgMode == Qt::OpaqueMode) { -
6363 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal()); -
6364 q->fillRect(rect, state->bgBrush); -
6365 } -
6366 -
6367 if (q->pen().style() == Qt::NoPen) -
6368 return; -
6369 -
6370 const QPainter::RenderHints oldRenderHints = state->renderHints; -
6371 if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) { -
6372 // draw antialias decoration (underline/overline/strikeout) with -
6373 // transformed text -
6374 -
6375 bool aa = true; -
6376 const QTransform &m = state->matrix; -
6377 if (state->matrix.type() < QTransform::TxShear) { -
6378 bool isPlain90DegreeRotation = -
6379 (qFuzzyIsNull(m.m11()) -
6380 && qFuzzyIsNull(m.m12() - qreal(1)) -
6381 && qFuzzyIsNull(m.m21() + qreal(1)) -
6382 && qFuzzyIsNull(m.m22()) -
6383 ) -
6384 || -
6385 (qFuzzyIsNull(m.m11() + qreal(1)) -
6386 && qFuzzyIsNull(m.m12()) -
6387 && qFuzzyIsNull(m.m21()) -
6388 && qFuzzyIsNull(m.m22() + qreal(1)) -
6389 ) -
6390 || -
6391 (qFuzzyIsNull(m.m11()) -
6392 && qFuzzyIsNull(m.m12() + qreal(1)) -
6393 && qFuzzyIsNull(m.m21() - qreal(1)) -
6394 && qFuzzyIsNull(m.m22()) -
6395 ) -
6396 ; -
6397 aa = !isPlain90DegreeRotation; -
6398 } -
6399 if (aa) -
6400 q->setRenderHint(QPainter::Antialiasing, true); -
6401 } -
6402 -
6403 if (!extended) -
6404 updateState(state); -
6405 -
6406 if (!ti.glyphs.numGlyphs) { -
6407 // nothing to do -
6408 } else if (ti.fontEngine->type() == QFontEngine::Multi) { -
6409 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine); -
6410 -
6411 const QGlyphLayout &glyphs = ti.glyphs; -
6412 int which = glyphs.glyphs[0] >> 24; -
6413 -
6414 qreal x = p.x(); -
6415 qreal y = p.y(); -
6416 -
6417 bool rtl = ti.flags & QTextItem::RightToLeft; -
6418 if (rtl) -
6419 x += ti.width.toReal(); -
6420 -
6421 int start = 0; -
6422 int end, i; -
6423 for (end = 0; end < ti.glyphs.numGlyphs; ++end) { -
6424 const int e = glyphs.glyphs[end] >> 24; -
6425 if (e == which) -
6426 continue; -
6427 -
6428 -
6429 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start); -
6430 ti2.width = 0; -
6431 // set the high byte to zero and calc the width -
6432 for (i = start; i < end; ++i) { -
6433 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff; -
6434 ti2.width += ti.glyphs.effectiveAdvance(i); -
6435 } -
6436 -
6437 if (rtl) -
6438 x -= ti2.width.toReal(); -
6439 -
6440 engine->drawTextItem(QPointF(x, y), ti2); -
6441 -
6442 if (!rtl) -
6443 x += ti2.width.toReal(); -
6444 -
6445 // reset the high byte for all glyphs and advance to the next sub-string -
6446 const int hi = which << 24; -
6447 for (i = start; i < end; ++i) { -
6448 glyphs.glyphs[i] = hi | glyphs.glyphs[i]; -
6449 } -
6450 -
6451 // change engine -
6452 start = end; -
6453 which = e; -
6454 } -
6455 -
6456 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start); -
6457 ti2.width = 0; -
6458 // set the high byte to zero and calc the width -
6459 for (i = start; i < end; ++i) { -
6460 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff; -
6461 ti2.width += ti.glyphs.effectiveAdvance(i); -
6462 } -
6463 -
6464 if (rtl) -
6465 x -= ti2.width.toReal(); -
6466 -
6467 if (extended) -
6468 extended->drawTextItem(QPointF(x, y), ti2); -
6469 else -
6470 engine->drawTextItem(QPointF(x,y), ti2); -
6471 -
6472 // reset the high byte for all glyphs -
6473 const int hi = which << 24; -
6474 for (i = start; i < end; ++i) -
6475 glyphs.glyphs[i] = hi | glyphs.glyphs[i]; -
6476 -
6477 } else { -
6478 if (extended) -
6479 extended->drawTextItem(p, ti); -
6480 else -
6481 engine->drawTextItem(p, ti); -
6482 } -
6483 drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle, -
6484 ti.flags, ti.width.toReal(), ti.charFormat); -
6485 -
6486 if (state->renderHints != oldRenderHints) { -
6487 state->renderHints = oldRenderHints; -
6488 if (extended) -
6489 extended->renderHintsChanged(); -
6490 else -
6491 state->dirtyFlags |= QPaintEngine::DirtyHints; -
6492 } -
6493} -
6494 -
6495/*! -
6496 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text) -
6497 -
6498 Returns the bounding rectangle of the \a text as it will appear -
6499 when drawn inside the given \a rectangle with the specified \a -
6500 flags using the currently set font(); i.e the function tells you -
6501 where the drawText() function will draw when given the same -
6502 arguments. -
6503 -
6504 If the \a text does not fit within the given \a rectangle using -
6505 the specified \a flags, the function returns the required -
6506 rectangle. -
6507 -
6508 The \a flags argument is a bitwise OR of the following flags: -
6509 \list -
6510 \li Qt::AlignLeft -
6511 \li Qt::AlignRight -
6512 \li Qt::AlignHCenter -
6513 \li Qt::AlignTop -
6514 \li Qt::AlignBottom -
6515 \li Qt::AlignVCenter -
6516 \li Qt::AlignCenter -
6517 \li Qt::TextSingleLine -
6518 \li Qt::TextExpandTabs -
6519 \li Qt::TextShowMnemonic -
6520 \li Qt::TextWordWrap -
6521 \li Qt::TextIncludeTrailingSpaces -
6522 \endlist -
6523 If several of the horizontal or several of the vertical alignment -
6524 flags are set, the resulting alignment is undefined. -
6525 -
6526 \sa drawText(), Qt::Alignment, Qt::TextFlag -
6527*/ -
6528 -
6529/*! -
6530 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags, -
6531 const QString &text) -
6532 -
6533 \overload -
6534 -
6535 Returns the bounding rectangle of the \a text as it will appear -
6536 when drawn inside the given \a rectangle with the specified \a -
6537 flags using the currently set font(). -
6538*/ -
6539 -
6540/*! -
6541 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags, -
6542 const QString &text); -
6543 -
6544 \overload -
6545 -
6546 Returns the bounding rectangle of the given \a text as it will -
6547 appear when drawn inside the rectangle beginning at the point -
6548 (\a{x}, \a{y}) with width \a w and height \a h. -
6549*/ -
6550QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str) -
6551{ -
6552 if (str.isEmpty()) -
6553 return QRect(rect.x(),rect.y(), 0,0); -
6554 QRect brect; -
6555 drawText(rect, flags | Qt::TextDontPrint, str, &brect); -
6556 return brect; -
6557} -
6558 -
6559 -
6560 -
6561QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str) -
6562{ -
6563 if (str.isEmpty()) -
6564 return QRectF(rect.x(),rect.y(), 0,0); -
6565 QRectF brect; -
6566 drawText(rect, flags | Qt::TextDontPrint, str, &brect); -
6567 return brect; -
6568} -
6569 -
6570/*! -
6571 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, -
6572 const QString &text, const QTextOption &option) -
6573 -
6574 \overload -
6575 -
6576 Instead of specifying flags as a bitwise OR of the -
6577 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes -
6578 an \a option argument. The QTextOption class provides a -
6579 description of general rich text properties. -
6580 -
6581 \sa QTextOption -
6582*/ -
6583QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o) -
6584{ -
6585 Q_D(QPainter); -
6586 -
6587 if (!d->engine || text.length() == 0) -
6588 return QRectF(r.x(),r.y(), 0,0); -
6589 -
6590 QRectF br; -
6591 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this); -
6592 return br; -
6593} -
6594 -
6595/*! -
6596 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position) -
6597 -
6598 Draws a tiled \a pixmap, inside the given \a rectangle with its -
6599 origin at the given \a position. -
6600 -
6601 Calling drawTiledPixmap() is similar to calling drawPixmap() -
6602 several times to fill (tile) an area with a pixmap, but is -
6603 potentially much more efficient depending on the underlying window -
6604 system. -
6605 -
6606 \sa drawPixmap() -
6607*/ -
6608void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp) -
6609{ -
6610#ifdef QT_DEBUG_DRAW -
6611 if (qt_show_painter_debug_output) -
6612 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n", -
6613 r.x(), r.y(), r.width(), r.height(), -
6614 pixmap.width(), pixmap.height(), -
6615 sp.x(), sp.y()); -
6616#endif -
6617 -
6618 Q_D(QPainter); -
6619 if (!d->engine || pixmap.isNull() || r.isEmpty()) -
6620 return; -
6621 -
6622#ifndef QT_NO_DEBUG -
6623 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true); -
6624#endif -
6625 -
6626 qreal sw = pixmap.width(); -
6627 qreal sh = pixmap.height(); -
6628 qreal sx = sp.x(); -
6629 qreal sy = sp.y(); -
6630 if (sx < 0) -
6631 sx = qRound(sw) - qRound(-sx) % qRound(sw); -
6632 else -
6633 sx = qRound(sx) % qRound(sw); -
6634 if (sy < 0) -
6635 sy = qRound(sh) - -qRound(sy) % qRound(sh); -
6636 else -
6637 sy = qRound(sy) % qRound(sh); -
6638 -
6639 -
6640 if (d->extended) { -
6641 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy)); -
6642 return; -
6643 } -
6644 -
6645 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap()) -
6646 fillRect(r, d->state->bgBrush); -
6647 -
6648 d->updateState(d->state); -
6649 if ((d->state->matrix.type() > QTransform::TxTranslate -
6650 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) -
6651 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))) -
6652 { -
6653 save(); -
6654 setBackgroundMode(Qt::TransparentMode); -
6655 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform); -
6656 setBrush(QBrush(d->state->pen.color(), pixmap)); -
6657 setPen(Qt::NoPen); -
6658 -
6659 // If there is no rotation involved we have to make sure we use the -
6660 // antialiased and not the aliased coordinate system by rounding the coordinates. -
6661 if (d->state->matrix.type() <= QTransform::TxScale) { -
6662 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix); -
6663 -
6664 if (d->state->matrix.type() <= QTransform::TxTranslate) { -
6665 sx = qRound(sx); -
6666 sy = qRound(sy); -
6667 } -
6668 -
6669 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy)); -
6670 drawRect(QRectF(p, r.size())); -
6671 } else { -
6672 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy)); -
6673 drawRect(r); -
6674 } -
6675 restore(); -
6676 return; -
6677 } -
6678 -
6679 qreal x = r.x(); -
6680 qreal y = r.y(); -
6681 if (d->state->matrix.type() == QTransform::TxTranslate -
6682 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) { -
6683 x += d->state->matrix.dx(); -
6684 y += d->state->matrix.dy(); -
6685 } -
6686 -
6687 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy)); -
6688} -
6689 -
6690/*! -
6691 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap, -
6692 const QPoint &position = QPoint()) -
6693 \overload -
6694 -
6695 Draws a tiled \a pixmap, inside the given \a rectangle with its -
6696 origin at the given \a position. -
6697*/ -
6698 -
6699/*! -
6700 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const -
6701 QPixmap &pixmap, int sx, int sy); -
6702 \overload -
6703 -
6704 Draws a tiled \a pixmap in the specified rectangle. -
6705 -
6706 (\a{x}, \a{y}) specifies the top-left point in the paint device -
6707 that is to be drawn onto; with the given \a width and \a -
6708 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a -
6709 pixmap that is to be drawn; this defaults to (0, 0). -
6710*/ -
6711 -
6712#ifndef QT_NO_PICTURE -
6713 -
6714/*! -
6715 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture) -
6716 -
6717 Replays the given \a picture at the given \a point. -
6718 -
6719 The QPicture class is a paint device that records and replays -
6720 QPainter commands. A picture serializes the painter commands to an -
6721 IO device in a platform-independent format. Everything that can be -
6722 painted on a widget or pixmap can also be stored in a picture. -
6723 -
6724 This function does exactly the same as QPicture::play() when -
6725 called with \a point = QPoint(0, 0). -
6726 -
6727 \table 100% -
6728 \row -
6729 \li -
6730 \snippet code/src_gui_painting_qpainter.cpp 18 -
6731 \endtable -
6732 -
6733 \sa QPicture::play() -
6734*/ -
6735 -
6736void QPainter::drawPicture(const QPointF &p, const QPicture &picture) -
6737{ -
6738 Q_D(QPainter); -
6739 -
6740 if (!d->engine) -
6741 return; -
6742 -
6743 if (!d->extended) -
6744 d->updateState(d->state); -
6745 -
6746 save(); -
6747 translate(p); -
6748 const_cast<QPicture *>(&picture)->play(this); -
6749 restore(); -
6750} -
6751 -
6752/*! -
6753 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture) -
6754 \overload -
6755 -
6756 Replays the given \a picture at the given \a point. -
6757*/ -
6758 -
6759/*! -
6760 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture) -
6761 \overload -
6762 -
6763 Draws the given \a picture at point (\a x, \a y). -
6764*/ -
6765 -
6766#endif // QT_NO_PICTURE -
6767 -
6768/*! -
6769 \fn void QPainter::eraseRect(const QRectF &rectangle) -
6770 -
6771 Erases the area inside the given \a rectangle. Equivalent to -
6772 calling -
6773 \snippet code/src_gui_painting_qpainter.cpp 19 -
6774 -
6775 \sa fillRect() -
6776*/ -
6777void QPainter::eraseRect(const QRectF &r) -
6778{ -
6779 Q_D(QPainter); -
6780 -
6781 fillRect(r, d->state->bgBrush); -
6782} -
6783 -
6784static inline bool needsResolving(const QBrush &brush) -
6785{ -
6786 Qt::BrushStyle s = brush.style(); -
6787 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern || -
6788 s == Qt::ConicalGradientPattern) && -
6789 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode); -
6790} -
6791 -
6792/*! -
6793 \fn void QPainter::eraseRect(const QRect &rectangle) -
6794 \overload -
6795 -
6796 Erases the area inside the given \a rectangle. -
6797*/ -
6798 -
6799/*! -
6800 \fn void QPainter::eraseRect(int x, int y, int width, int height) -
6801 \overload -
6802 -
6803 Erases the area inside the rectangle beginning at (\a x, \a y) -
6804 with the given \a width and \a height. -
6805*/ -
6806 -
6807 -
6808/*! -
6809 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style) -
6810 \overload -
6811 -
6812 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a -
6813 width and \a height, using the brush \a style specified. -
6814 -
6815 \since 4.5 -
6816*/ -
6817 -
6818/*! -
6819 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style) -
6820 \overload -
6821 -
6822 Fills the given \a rectangle with the brush \a style specified. -
6823 -
6824 \since 4.5 -
6825*/ -
6826 -
6827/*! -
6828 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style) -
6829 \overload -
6830 -
6831 Fills the given \a rectangle with the brush \a style specified. -
6832 -
6833 \since 4.5 -
6834*/ -
6835 -
6836/*! -
6837 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush) -
6838 -
6839 Fills the given \a rectangle with the \a brush specified. -
6840 -
6841 Alternatively, you can specify a QColor instead of a QBrush; the -
6842 QBrush constructor (taking a QColor argument) will automatically -
6843 create a solid pattern brush. -
6844 -
6845 \sa drawRect() -
6846*/ -
6847void QPainter::fillRect(const QRectF &r, const QBrush &brush) -
6848{ -
6849 Q_D(QPainter); -
6850 -
6851 if (!d->engine) -
6852 return; -
6853 -
6854 if (d->extended) { -
6855 const QGradient *g = brush.gradient(); -
6856 if (!g || g->coordinateMode() == QGradient::LogicalMode) { -
6857 d->extended->fillRect(r, brush); -
6858 return; -
6859 } -
6860 } -
6861 -
6862 QPen oldPen = pen(); -
6863 QBrush oldBrush = this->brush(); -
6864 setPen(Qt::NoPen); -
6865 if (brush.style() == Qt::SolidPattern) { -
6866 d->colorBrush.setStyle(Qt::SolidPattern); -
6867 d->colorBrush.setColor(brush.color()); -
6868 setBrush(d->colorBrush); -
6869 } else { -
6870 setBrush(brush); -
6871 } -
6872 -
6873 drawRect(r); -
6874 setBrush(oldBrush); -
6875 setPen(oldPen); -
6876} -
6877 -
6878/*! -
6879 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush) -
6880 \overload -
6881 -
6882 Fills the given \a rectangle with the specified \a brush. -
6883*/ -
6884 -
6885void QPainter::fillRect(const QRect &r, const QBrush &brush) -
6886{ -
6887 Q_D(QPainter); -
6888 -
6889 if (!d->engine) -
6890 return; -
6891 -
6892 if (d->extended) { -
6893 const QGradient *g = brush.gradient(); -
6894 if (!g || g->coordinateMode() == QGradient::LogicalMode) { -
6895 d->extended->fillRect(r, brush); -
6896 return; -
6897 } -
6898 } -
6899 -
6900 QPen oldPen = pen(); -
6901 QBrush oldBrush = this->brush(); -
6902 setPen(Qt::NoPen); -
6903 if (brush.style() == Qt::SolidPattern) { -
6904 d->colorBrush.setStyle(Qt::SolidPattern); -
6905 d->colorBrush.setColor(brush.color()); -
6906 setBrush(d->colorBrush); -
6907 } else { -
6908 setBrush(brush); -
6909 } -
6910 -
6911 drawRect(r); -
6912 setBrush(oldBrush); -
6913 setPen(oldPen); -
6914} -
6915 -
6916 -
6917 -
6918/*! -
6919 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color) -
6920 \overload -
6921 -
6922 Fills the given \a rectangle with the \a color specified. -
6923 -
6924 \since 4.5 -
6925*/ -
6926void QPainter::fillRect(const QRect &r, const QColor &color) -
6927{ -
6928 Q_D(QPainter); -
6929 -
6930 if (!d->engine) -
6931 return; -
6932 -
6933 if (d->extended) { -
6934 d->extended->fillRect(r, color); -
6935 return; -
6936 } -
6937 -
6938 fillRect(r, QBrush(color)); -
6939} -
6940 -
6941 -
6942/*! -
6943 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color) -
6944 \overload -
6945 -
6946 Fills the given \a rectangle with the \a color specified. -
6947 -
6948 \since 4.5 -
6949*/ -
6950void QPainter::fillRect(const QRectF &r, const QColor &color) -
6951{ -
6952 Q_D(QPainter); -
6953 -
6954 if (!d->engine) -
6955 return; -
6956 -
6957 if (d->extended) { -
6958 d->extended->fillRect(r, color); -
6959 return; -
6960 } -
6961 -
6962 fillRect(r, QBrush(color)); -
6963} -
6964 -
6965/*! -
6966 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush) -
6967 -
6968 \overload -
6969 -
6970 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a -
6971 width and \a height, using the given \a brush. -
6972*/ -
6973 -
6974/*! -
6975 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color) -
6976 -
6977 \overload -
6978 -
6979 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a -
6980 width and \a height, using the given \a color. -
6981 -
6982 \since 4.5 -
6983*/ -
6984 -
6985/*! -
6986 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color) -
6987 -
6988 \overload -
6989 -
6990 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a -
6991 width and \a height, using the given \a color. -
6992 -
6993 \since 4.5 -
6994*/ -
6995 -
6996/*! -
6997 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color); -
6998 -
6999 \overload -
7000 -
7001 Fills the given \a rectangle with the specified \a color. -
7002 -
7003 \since 4.5 -
7004*/ -
7005 -
7006/*! -
7007 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color); -
7008 -
7009 \overload -
7010 -
7011 Fills the given \a rectangle with the specified \a color. -
7012 -
7013 \since 4.5 -
7014*/ -
7015 -
7016/*! -
7017 Sets the given render \a hint on the painter if \a on is true; -
7018 otherwise clears the render hint. -
7019 -
7020 \sa setRenderHints(), renderHints(), {QPainter#Rendering -
7021 Quality}{Rendering Quality} -
7022*/ -
7023void QPainter::setRenderHint(RenderHint hint, bool on) -
7024{ -
7025#ifdef QT_DEBUG_DRAW -
7026 if (qt_show_painter_debug_output) -
7027 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off"); -
7028#endif -
7029 -
7030#ifndef QT_NO_DEBUG -
7031 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt(); -
7032 if (hint == QPainter::Antialiasing && antialiasingDisabled) -
7033 return; -
7034#endif -
7035 -
7036 setRenderHints(hint, on); -
7037} -
7038 -
7039/*! -
7040 \since 4.2 -
7041 -
7042 Sets the given render \a hints on the painter if \a on is true; -
7043 otherwise clears the render hints. -
7044 -
7045 \sa setRenderHint(), renderHints(), {QPainter#Rendering -
7046 Quality}{Rendering Quality} -
7047*/ -
7048 -
7049void QPainter::setRenderHints(RenderHints hints, bool on) -
7050{ -
7051 Q_D(QPainter); -
7052 -
7053 if (!d->engine) { -
7054 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints"); -
7055 return; -
7056 } -
7057 -
7058 if (on) -
7059 d->state->renderHints |= hints; -
7060 else -
7061 d->state->renderHints &= ~hints; -
7062 -
7063 if (d->extended) -
7064 d->extended->renderHintsChanged(); -
7065 else -
7066 d->state->dirtyFlags |= QPaintEngine::DirtyHints; -
7067} -
7068 -
7069/*! -
7070 Returns a flag that specifies the rendering hints that are set for -
7071 this painter. -
7072 -
7073 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality} -
7074*/ -
7075QPainter::RenderHints QPainter::renderHints() const -
7076{ -
7077 Q_D(const QPainter); -
7078 -
7079 if (!d->engine) -
7080 return 0; -
7081 -
7082 return d->state->renderHints; -
7083} -
7084 -
7085/*! -
7086 \fn bool QPainter::testRenderHint(RenderHint hint) const -
7087 \since 4.3 -
7088 -
7089 Returns true if \a hint is set; otherwise returns false. -
7090 -
7091 \sa renderHints(), setRenderHint() -
7092*/ -
7093 -
7094/*! -
7095 Returns true if view transformation is enabled; otherwise returns -
7096 false. -
7097 -
7098 \sa setViewTransformEnabled(), worldTransform() -
7099*/ -
7100 -
7101bool QPainter::viewTransformEnabled() const -
7102{ -
7103 Q_D(const QPainter); -
7104 if (!d->engine) { -
7105 qWarning("QPainter::viewTransformEnabled: Painter not active"); -
7106 return false; -
7107 } -
7108 return d->state->VxF; -
7109} -
7110 -
7111/*! -
7112 \fn void QPainter::setWindow(const QRect &rectangle) -
7113 -
7114 Sets the painter's window to the given \a rectangle, and enables -
7115 view transformations. -
7116 -
7117 The window rectangle is part of the view transformation. The -
7118 window specifies the logical coordinate system. Its sister, the -
7119 viewport(), specifies the device coordinate system. -
7120 -
7121 The default window rectangle is the same as the device's -
7122 rectangle. -
7123 -
7124 \sa window(), viewTransformEnabled(), {Coordinate -
7125 System#Window-Viewport Conversion}{Window-Viewport Conversion} -
7126*/ -
7127 -
7128/*! -
7129 \fn void QPainter::setWindow(int x, int y, int width, int height) -
7130 \overload -
7131 -
7132 Sets the painter's window to the rectangle beginning at (\a x, \a -
7133 y) and the given \a width and \a height. -
7134*/ -
7135 -
7136void QPainter::setWindow(const QRect &r) -
7137{ -
7138#ifdef QT_DEBUG_DRAW -
7139 if (qt_show_painter_debug_output) -
7140 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height()); -
7141#endif -
7142 -
7143 Q_D(QPainter); -
7144 -
7145 if (!d->engine) { -
7146 qWarning("QPainter::setWindow: Painter not active"); -
7147 return; -
7148 } -
7149 -
7150 d->state->wx = r.x(); -
7151 d->state->wy = r.y(); -
7152 d->state->ww = r.width(); -
7153 d->state->wh = r.height(); -
7154 -
7155 d->state->VxF = true; -
7156 d->updateMatrix(); -
7157} -
7158 -
7159/*! -
7160 Returns the window rectangle. -
7161 -
7162 \sa setWindow(), setViewTransformEnabled() -
7163*/ -
7164 -
7165QRect QPainter::window() const -
7166{ -
7167 Q_D(const QPainter); -
7168 if (!d->engine) { -
7169 qWarning("QPainter::window: Painter not active"); -
7170 return QRect(); -
7171 } -
7172 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh); -
7173} -
7174 -
7175/*! -
7176 \fn void QPainter::setViewport(const QRect &rectangle) -
7177 -
7178 Sets the painter's viewport rectangle to the given \a rectangle, -
7179 and enables view transformations. -
7180 -
7181 The viewport rectangle is part of the view transformation. The -
7182 viewport specifies the device coordinate system. Its sister, the -
7183 window(), specifies the logical coordinate system. -
7184 -
7185 The default viewport rectangle is the same as the device's -
7186 rectangle. -
7187 -
7188 \sa viewport(), viewTransformEnabled(), {Coordinate -
7189 System#Window-Viewport Conversion}{Window-Viewport Conversion} -
7190*/ -
7191 -
7192/*! -
7193 \fn void QPainter::setViewport(int x, int y, int width, int height) -
7194 \overload -
7195 -
7196 Sets the painter's viewport rectangle to be the rectangle -
7197 beginning at (\a x, \a y) with the given \a width and \a height. -
7198*/ -
7199 -
7200void QPainter::setViewport(const QRect &r) -
7201{ -
7202#ifdef QT_DEBUG_DRAW -
7203 if (qt_show_painter_debug_output) -
7204 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height()); -
7205#endif -
7206 -
7207 Q_D(QPainter); -
7208 -
7209 if (!d->engine) { -
7210 qWarning("QPainter::setViewport: Painter not active"); -
7211 return; -
7212 } -
7213 -
7214 d->state->vx = r.x(); -
7215 d->state->vy = r.y(); -
7216 d->state->vw = r.width(); -
7217 d->state->vh = r.height(); -
7218 -
7219 d->state->VxF = true; -
7220 d->updateMatrix(); -
7221} -
7222 -
7223/*! -
7224 Returns the viewport rectangle. -
7225 -
7226 \sa setViewport(), setViewTransformEnabled() -
7227*/ -
7228 -
7229QRect QPainter::viewport() const -
7230{ -
7231 Q_D(const QPainter); -
7232 if (!d->engine) { -
7233 qWarning("QPainter::viewport: Painter not active"); -
7234 return QRect(); -
7235 } -
7236 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh); -
7237} -
7238 -
7239/*! -
7240 Enables view transformations if \a enable is true, or disables -
7241 view transformations if \a enable is false. -
7242 -
7243 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport -
7244 Conversion}{Window-Viewport Conversion} -
7245*/ -
7246 -
7247void QPainter::setViewTransformEnabled(bool enable) -
7248{ -
7249#ifdef QT_DEBUG_DRAW -
7250 if (qt_show_painter_debug_output) -
7251 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable); -
7252#endif -
7253 -
7254 Q_D(QPainter); -
7255 -
7256 if (!d->engine) { -
7257 qWarning("QPainter::setViewTransformEnabled: Painter not active"); -
7258 return; -
7259 } -
7260 -
7261 if (enable == d->state->VxF) -
7262 return; -
7263 -
7264 d->state->VxF = enable; -
7265 d->updateMatrix(); -
7266} -
7267 -
7268/*! -
7269 \threadsafe -
7270 -
7271 \obsolete -
7272 -
7273 Please use QWidget::render() instead. -
7274 -
7275 Redirects all paint commands for the given paint \a device, to the -
7276 \a replacement device. The optional point \a offset defines an -
7277 offset within the source device. -
7278 -
7279 The redirection will not be effective until the begin() function -
7280 has been called; make sure to call end() for the given \a -
7281 device's painter (if any) before redirecting. Call -
7282 restoreRedirected() to restore the previous redirection. -
7283 -
7284 \warning Making use of redirections in the QPainter API implies -
7285 that QPainter::begin() and QPaintDevice destructors need to hold -
7286 a mutex for a short period. This can impact performance. Use of -
7287 QWidget::render is strongly encouraged. -
7288 -
7289 \sa redirected(), restoreRedirected() -
7290*/ -
7291void QPainter::setRedirected(const QPaintDevice *device, -
7292 QPaintDevice *replacement, -
7293 const QPoint &offset) -
7294{ -
7295 Q_ASSERT(device != 0); -
7296 Q_UNUSED(device) -
7297 Q_UNUSED(replacement) -
7298 Q_UNUSED(offset) -
7299 qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead"); -
7300} -
7301 -
7302/*! -
7303 \threadsafe -
7304 -
7305 \obsolete -
7306 -
7307 Using QWidget::render() obsoletes the use of this function. -
7308 -
7309 Restores the previous redirection for the given \a device after a -
7310 call to setRedirected(). -
7311 -
7312 \warning Making use of redirections in the QPainter API implies -
7313 that QPainter::begin() and QPaintDevice destructors need to hold -
7314 a mutex for a short period. This can impact performance. Use of -
7315 QWidget::render is strongly encouraged. -
7316 -
7317 \sa redirected() -
7318 */ -
7319void QPainter::restoreRedirected(const QPaintDevice *device) -
7320{ -
7321 Q_UNUSED(device) -
7322 qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead"); -
7323} -
7324 -
7325/*! -
7326 \threadsafe -
7327 -
7328 \obsolete -
7329 -
7330 Using QWidget::render() obsoletes the use of this function. -
7331 -
7332 Returns the replacement for given \a device. The optional out -
7333 parameter \a offset returns the offset within the replaced device. -
7334 -
7335 \warning Making use of redirections in the QPainter API implies -
7336 that QPainter::begin() and QPaintDevice destructors need to hold -
7337 a mutex for a short period. This can impact performance. Use of -
7338 QWidget::render is strongly encouraged. -
7339 -
7340 \sa setRedirected(), restoreRedirected() -
7341*/ -
7342QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) -
7343{ -
7344 Q_UNUSED(device) -
7345 Q_UNUSED(offset) -
7346 return 0; -
7347} -
7348 -
7349void qt_format_text(const QFont &fnt, const QRectF &_r, -
7350 int tf, const QString& str, QRectF *brect, -
7351 int tabstops, int *ta, int tabarraylen, -
7352 QPainter *painter) -
7353{ -
7354 qt_format_text(fnt, _r, -
7355 tf, 0, str, brect, -
7356 tabstops, ta, tabarraylen, -
7357 painter); -
7358} -
7359void qt_format_text(const QFont &fnt, const QRectF &_r, -
7360 int tf, const QTextOption *option, const QString& str, QRectF *brect, -
7361 int tabstops, int *ta, int tabarraylen, -
7362 QPainter *painter) -
7363{ -
7364 -
7365 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags -
7366 -
7367 if (option) { -
7368 tf |= option->alignment(); -
7369 if (option->wrapMode() != QTextOption::NoWrap) -
7370 tf |= Qt::TextWordWrap; -
7371 -
7372 if (option->flags() & QTextOption::IncludeTrailingSpaces) -
7373 tf |= Qt::TextIncludeTrailingSpaces; -
7374 -
7375 if (option->tabStop() >= 0 || !option->tabArray().isEmpty()) -
7376 tf |= Qt::TextExpandTabs; -
7377 } -
7378 -
7379 // we need to copy r here to protect against the case (&r == brect). -
7380 QRectF r(_r); -
7381 -
7382 bool dontclip = (tf & Qt::TextDontClip); -
7383 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere); -
7384 bool singleline = (tf & Qt::TextSingleLine); -
7385 bool showmnemonic = (tf & Qt::TextShowMnemonic); -
7386 bool hidemnmemonic = (tf & Qt::TextHideMnemonic); -
7387 -
7388 Qt::LayoutDirection layout_direction; -
7389 if (tf & Qt::TextForceLeftToRight) -
7390 layout_direction = Qt::LeftToRight; -
7391 else if (tf & Qt::TextForceRightToLeft) -
7392 layout_direction = Qt::RightToLeft; -
7393 else if (option) -
7394 layout_direction = option->textDirection(); -
7395 else if (painter) -
7396 layout_direction = painter->layoutDirection(); -
7397 else -
7398 layout_direction = Qt::LeftToRight; -
7399 -
7400 tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf)); -
7401 -
7402 bool isRightToLeft = layout_direction == Qt::RightToLeft; -
7403 bool expandtabs = ((tf & Qt::TextExpandTabs) && -
7404 (((tf & Qt::AlignLeft) && !isRightToLeft) || -
7405 ((tf & Qt::AlignRight) && isRightToLeft))); -
7406 -
7407 if (!painter) -
7408 tf |= Qt::TextDontPrint; -
7409 -
7410 uint maxUnderlines = 0; -
7411 int numUnderlines = 0; -
7412 QVarLengthArray<int, 32> underlinePositions(1); -
7413 -
7414 QFontMetricsF fm(fnt); -
7415 QString text = str; -
7416 int offset = 0; -
7417start_lengthVariant: -
7418 bool hasMoreLengthVariants = false; -
7419 // compatible behaviour to the old implementation. Replace -
7420 // tabs by spaces -
7421 int old_offset = offset; -
7422 for (; offset < text.length(); offset++) { -
7423 QChar chr = text.at(offset); -
7424 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) { -
7425 text[offset] = QLatin1Char(' '); -
7426 } else if (chr == QLatin1Char('\n')) { -
7427 text[offset] = QChar::LineSeparator; -
7428 } else if (chr == QLatin1Char('&')) { -
7429 ++maxUnderlines; -
7430 } else if (chr == QLatin1Char('\t')) { -
7431 if (!expandtabs) { -
7432 text[offset] = QLatin1Char(' '); -
7433 } else if (!tabarraylen && !tabstops) { -
7434 tabstops = qRound(fm.width(QLatin1Char('x'))*8); -
7435 } -
7436 } else if (chr == QChar(ushort(0x9c))) { -
7437 // string with multiple length variants -
7438 hasMoreLengthVariants = true; -
7439 break; -
7440 } -
7441 } -
7442 -
7443 int length = offset - old_offset; -
7444 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) { -
7445 underlinePositions.resize(maxUnderlines + 1); -
7446 -
7447 QChar *cout = text.data() + old_offset; -
7448 QChar *cin = cout; -
7449 int l = length; -
7450 while (l) { -
7451 if (*cin == QLatin1Char('&')) { -
7452 ++cin; -
7453 --length; -
7454 --l; -
7455 if (!l) -
7456 break; -
7457 if (*cin != QLatin1Char('&') && !hidemnmemonic) -
7458 underlinePositions[numUnderlines++] = cout - text.data() - old_offset; -
7459 } -
7460 *cout = *cin; -
7461 ++cout; -
7462 ++cin; -
7463 --l; -
7464 } -
7465 } -
7466 -
7467 // no need to do extra work for underlines if we don't paint -
7468 if (tf & Qt::TextDontPrint) -
7469 numUnderlines = 0; -
7470 -
7471 underlinePositions[numUnderlines] = -1; -
7472 qreal height = 0; -
7473 qreal width = 0; -
7474 -
7475 QString finalText = text.mid(old_offset, length); -
7476 QStackTextEngine engine(finalText, fnt); -
7477 if (option) { -
7478 engine.option = *option; -
7479 } -
7480 -
7481 if (engine.option.tabStop() < 0 && tabstops > 0) -
7482 engine.option.setTabStop(tabstops); -
7483 -
7484 if (engine.option.tabs().isEmpty() && ta) { -
7485 QList<qreal> tabs; -
7486 for (int i = 0; i < tabarraylen; i++) -
7487 tabs.append(qreal(ta[i])); -
7488 engine.option.setTabArray(tabs); -
7489 } -
7490 -
7491 engine.option.setTextDirection(layout_direction); -
7492 if (tf & Qt::AlignJustify) -
7493 engine.option.setAlignment(Qt::AlignJustify); -
7494 else -
7495 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice -
7496 -
7497 if (!option && (tf & Qt::TextWrapAnywhere)) -
7498 engine.option.setWrapMode(QTextOption::WrapAnywhere); -
7499 -
7500 if (tf & Qt::TextJustificationForced) -
7501 engine.forceJustification = true; -
7502 QTextLayout textLayout(&engine); -
7503 textLayout.setCacheEnabled(true); -
7504 textLayout.engine()->underlinePositions = underlinePositions.data(); -
7505 -
7506 if (finalText.isEmpty()) { -
7507 height = fm.height(); -
7508 width = 0; -
7509 tf |= Qt::TextDontPrint; -
7510 } else { -
7511 qreal lineWidth = 0x01000000; -
7512 if (wordwrap || (tf & Qt::TextJustificationForced)) -
7513 lineWidth = qMax<qreal>(0, r.width()); -
7514 if(!wordwrap) -
7515 tf |= Qt::TextIncludeTrailingSpaces; -
7516 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint); -
7517 textLayout.beginLayout(); -
7518 -
7519 qreal leading = fm.leading(); -
7520 height = -leading; -
7521 -
7522 while (1) { -
7523 QTextLine l = textLayout.createLine(); -
7524 if (!l.isValid()) -
7525 break; -
7526 -
7527 l.setLineWidth(lineWidth); -
7528 height += leading; -
7529 -
7530 // Make sure lines are positioned on whole pixels -
7531 height = qCeil(height); -
7532 l.setPosition(QPointF(0., height)); -
7533 height += textLayout.engine()->lines[l.lineNumber()].height().toReal(); -
7534 width = qMax(width, l.naturalTextWidth()); -
7535 if (!dontclip && !brect && height >= r.height()) -
7536 break; -
7537 } -
7538 textLayout.endLayout(); -
7539 } -
7540 -
7541 qreal yoff = 0; -
7542 qreal xoff = 0; -
7543 if (tf & Qt::AlignBottom) -
7544 yoff = r.height() - height; -
7545 else if (tf & Qt::AlignVCenter) -
7546 yoff = (r.height() - height)/2; -
7547 -
7548 if (tf & Qt::AlignRight) -
7549 xoff = r.width() - width; -
7550 else if (tf & Qt::AlignHCenter) -
7551 xoff = (r.width() - width)/2; -
7552 -
7553 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height); -
7554 -
7555 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) { -
7556 offset++; -
7557 goto start_lengthVariant; -
7558 } -
7559 if (brect) -
7560 *brect = bounds; -
7561 -
7562 if (!(tf & Qt::TextDontPrint)) { -
7563 bool restore = false; -
7564 if (!dontclip && !r.contains(bounds)) { -
7565 restore = true; -
7566 painter->save(); -
7567 painter->setClipRect(r, Qt::IntersectClip); -
7568 } -
7569 -
7570 for (int i = 0; i < textLayout.lineCount(); i++) { -
7571 QTextLine line = textLayout.lineAt(i); -
7572 QTextEngine *eng = textLayout.engine(); -
7573 eng->enableDelayDecorations(); -
7574 -
7575 qreal advance = line.horizontalAdvance(); -
7576 xoff = 0; -
7577 if (tf & Qt::AlignRight) { -
7578 xoff = r.width() - advance - -
7579 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal(); -
7580 } -
7581 else if (tf & Qt::AlignHCenter) -
7582 xoff = (r.width() - advance) / 2; -
7583 -
7584 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff)); -
7585 eng->drawDecorations(painter); -
7586 } -
7587 -
7588 if (restore) { -
7589 painter->restore(); -
7590 } -
7591 } -
7592} -
7593 -
7594/*! -
7595 Sets the layout direction used by the painter when drawing text, -
7596 to the specified \a direction. -
7597 -
7598 The default is Qt::LayoutDirectionAuto, which will implicitly determine the -
7599 direction from the text drawn. -
7600 -
7601 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings} -
7602*/ -
7603void QPainter::setLayoutDirection(Qt::LayoutDirection direction) -
7604{ -
7605 Q_D(QPainter); -
7606 if (d->state) -
7607 d->state->layoutDirection = direction; -
7608} -
7609 -
7610/*! -
7611 Returns the layout direction used by the painter when drawing text. -
7612 -
7613 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings} -
7614*/ -
7615Qt::LayoutDirection QPainter::layoutDirection() const -
7616{ -
7617 Q_D(const QPainter); -
7618 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto; -
7619} -
7620 -
7621QPainterState::QPainterState(const QPainterState *s) -
7622 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont), -
7623 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush), -
7624 clipRegion(s->clipRegion), clipPath(s->clipPath), -
7625 clipOperation(s->clipOperation), -
7626 renderHints(s->renderHints), clipInfo(s->clipInfo), -
7627 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix), -
7628 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh), -
7629 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh), -
7630 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF), -
7631 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter), -
7632 layoutDirection(s->layoutDirection), -
7633 composition_mode(s->composition_mode), -
7634 emulationSpecifier(s->emulationSpecifier), changeFlags(0) -
7635{ -
7636 dirtyFlags = s->dirtyFlags; -
7637} -
7638 -
7639QPainterState::QPainterState() -
7640 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip), -
7641 renderHints(0), -
7642 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0), -
7643 opacity(1), WxF(false), VxF(false), clipEnabled(true), -
7644 bgMode(Qt::TransparentMode), painter(0), -
7645 layoutDirection(QGuiApplication::layoutDirection()), -
7646 composition_mode(QPainter::CompositionMode_SourceOver), -
7647 emulationSpecifier(0), changeFlags(0) -
7648{ -
7649 dirtyFlags = 0; -
7650} -
7651 -
7652QPainterState::~QPainterState() -
7653{ -
7654} -
7655 -
7656void QPainterState::init(QPainter *p) { -
7657 bgBrush = Qt::white; -
7658 bgMode = Qt::TransparentMode; -
7659 WxF = false; -
7660 VxF = false; -
7661 clipEnabled = true; -
7662 wx = wy = ww = wh = 0; -
7663 vx = vy = vw = vh = 0; -
7664 painter = p; -
7665 pen = QPen(); -
7666 brushOrigin = QPointF(0, 0); -
7667 brush = QBrush(); -
7668 font = deviceFont = QFont(); -
7669 clipRegion = QRegion(); -
7670 clipPath = QPainterPath(); -
7671 clipOperation = Qt::NoClip; -
7672 clipInfo.clear(); -
7673 worldMatrix.reset(); -
7674 matrix.reset(); -
7675 layoutDirection = QGuiApplication::layoutDirection(); -
7676 composition_mode = QPainter::CompositionMode_SourceOver; -
7677 emulationSpecifier = 0; -
7678 dirtyFlags = 0; -
7679 changeFlags = 0; -
7680 renderHints = 0; -
7681 opacity = 1; -
7682} -
7683 -
7684/*! -
7685 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source, -
7686 Qt::ImageConversionFlags flags) -
7687 -
7688 Draws the rectangular portion \a source of the given \a image -
7689 into the \a target rectangle in the paint device. -
7690 -
7691 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree. -
7692 -
7693 If the image needs to be modified to fit in a lower-resolution -
7694 result (e.g. converting from 32-bit to 8-bit), use the \a flags to -
7695 specify how you would prefer this to happen. -
7696 -
7697 \table 100% -
7698 \row -
7699 \li -
7700 \snippet code/src_gui_painting_qpainter.cpp 20 -
7701 \endtable -
7702 -
7703 \sa drawPixmap() -
7704*/ -
7705 -
7706/*! -
7707 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source, -
7708 Qt::ImageConversionFlags flags) -
7709 \overload -
7710 -
7711 Draws the rectangular portion \a source of the given \a image -
7712 into the \a target rectangle in the paint device. -
7713 -
7714 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree. -
7715*/ -
7716 -
7717/*! -
7718 \fn void QPainter::drawImage(const QPointF &point, const QImage &image) -
7719 -
7720 \overload -
7721 -
7722 Draws the given \a image at the given \a point. -
7723*/ -
7724 -
7725/*! -
7726 \fn void QPainter::drawImage(const QPoint &point, const QImage &image) -
7727 -
7728 \overload -
7729 -
7730 Draws the given \a image at the given \a point. -
7731*/ -
7732 -
7733/*! -
7734 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source, -
7735 Qt::ImageConversionFlags flags = 0) -
7736 -
7737 \overload -
7738 -
7739 Draws the rectangular portion \a source of the given \a image with -
7740 its origin at the given \a point. -
7741*/ -
7742 -
7743/*! -
7744 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source, -
7745 Qt::ImageConversionFlags flags = 0) -
7746 \overload -
7747 -
7748 Draws the rectangular portion \a source of the given \a image with -
7749 its origin at the given \a point. -
7750*/ -
7751 -
7752/*! -
7753 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image) -
7754 -
7755 \overload -
7756 -
7757 Draws the given \a image into the given \a rectangle. -
7758 -
7759 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree. -
7760*/ -
7761 -
7762/*! -
7763 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image) -
7764 -
7765 \overload -
7766 -
7767 Draws the given \a image into the given \a rectangle. -
7768 -
7769 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree. -
7770*/ -
7771 -
7772/*! -
7773 \fn void QPainter::drawImage(int x, int y, const QImage &image, -
7774 int sx, int sy, int sw, int sh, -
7775 Qt::ImageConversionFlags flags) -
7776 \overload -
7777 -
7778 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into -
7779 the paint device. -
7780 -
7781 (\a{x}, \a{y}) specifies the top-left point in the paint device that is -
7782 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a -
7783 image that is to be drawn. The default is (0, 0). -
7784 -
7785 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn. -
7786 The default, (0, 0) (and negative) means all the way to the -
7787 bottom-right of the image. -
7788*/ -
7789 -
7790/*! -
7791 \class QPaintEngineState -
7792 \since 4.1 -
7793 \inmodule QtGui -
7794 -
7795 \brief The QPaintEngineState class provides information about the -
7796 active paint engine's current state. -
7797 \reentrant -
7798 -
7799 QPaintEngineState records which properties that have changed since -
7800 the last time the paint engine was updated, as well as their -
7801 current value. -
7802 -
7803 Which properties that have changed can at any time be retrieved -
7804 using the state() function. This function returns an instance of -
7805 the QPaintEngine::DirtyFlags type which stores an OR combination -
7806 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag -
7807 enum defines whether a property has changed since the last update -
7808 or not. -
7809 -
7810 If a property is marked with a dirty flag, its current value can -
7811 be retrieved using the corresponding get function: -
7812 -
7813 \target GetFunction -
7814 -
7815 \table -
7816 \header \li Property Flag \li Current Property Value -
7817 \row \li QPaintEngine::DirtyBackground \li backgroundBrush() -
7818 \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode() -
7819 \row \li QPaintEngine::DirtyBrush \li brush() -
7820 \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin() -
7821 \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath -
7822 \li clipOperation() -
7823 \row \li QPaintEngine::DirtyClipPath \li clipPath() -
7824 \row \li QPaintEngine::DirtyClipRegion \li clipRegion() -
7825 \row \li QPaintEngine::DirtyCompositionMode \li compositionMode() -
7826 \row \li QPaintEngine::DirtyFont \li font() -
7827 \row \li QPaintEngine::DirtyTransform \li transform() -
7828 \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled() -
7829 \row \li QPaintEngine::DirtyPen \li pen() -
7830 \row \li QPaintEngine::DirtyHints \li renderHints() -
7831 \endtable -
7832 -
7833 The QPaintEngineState class also provide the painter() function -
7834 which returns a pointer to the painter that is currently updating -
7835 the paint engine. -
7836 -
7837 An instance of this class, representing the current state of the -
7838 active paint engine, is passed as argument to the -
7839 QPaintEngine::updateState() function. The only situation in which -
7840 you will have to use this class directly is when implementing your -
7841 own paint engine. -
7842 -
7843 \sa QPaintEngine -
7844*/ -
7845 -
7846 -
7847/*! -
7848 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const -
7849 -
7850 Returns a combination of flags identifying the set of properties -
7851 that need to be updated when updating the paint engine's state -
7852 (i.e. during a call to the QPaintEngine::updateState() function). -
7853 -
7854 \sa QPaintEngine::updateState() -
7855*/ -
7856 -
7857 -
7858/*! -
7859 Returns the pen in the current paint engine state. -
7860 -
7861 This variable should only be used when the state() returns a -
7862 combination which includes the QPaintEngine::DirtyPen flag. -
7863 -
7864 \sa state(), QPaintEngine::updateState() -
7865*/ -
7866 -
7867QPen QPaintEngineState::pen() const -
7868{ -
7869 return static_cast<const QPainterState *>(this)->pen; -
7870} -
7871 -
7872/*! -
7873 Returns the brush in the current paint engine state. -
7874 -
7875 This variable should only be used when the state() returns a -
7876 combination which includes the QPaintEngine::DirtyBrush flag. -
7877 -
7878 \sa state(), QPaintEngine::updateState() -
7879*/ -
7880 -
7881QBrush QPaintEngineState::brush() const -
7882{ -
7883 return static_cast<const QPainterState *>(this)->brush; -
7884} -
7885 -
7886/*! -
7887 Returns the brush origin in the current paint engine state. -
7888 -
7889 This variable should only be used when the state() returns a -
7890 combination which includes the QPaintEngine::DirtyBrushOrigin flag. -
7891 -
7892 \sa state(), QPaintEngine::updateState() -
7893*/ -
7894 -
7895QPointF QPaintEngineState::brushOrigin() const -
7896{ -
7897 return static_cast<const QPainterState *>(this)->brushOrigin; -
7898} -
7899 -
7900/*! -
7901 Returns the background brush in the current paint engine state. -
7902 -
7903 This variable should only be used when the state() returns a -
7904 combination which includes the QPaintEngine::DirtyBackground flag. -
7905 -
7906 \sa state(), QPaintEngine::updateState() -
7907*/ -
7908 -
7909QBrush QPaintEngineState::backgroundBrush() const -
7910{ -
7911 return static_cast<const QPainterState *>(this)->bgBrush; -
7912} -
7913 -
7914/*! -
7915 Returns the background mode in the current paint engine -
7916 state. -
7917 -
7918 This variable should only be used when the state() returns a -
7919 combination which includes the QPaintEngine::DirtyBackgroundMode flag. -
7920 -
7921 \sa state(), QPaintEngine::updateState() -
7922*/ -
7923 -
7924Qt::BGMode QPaintEngineState::backgroundMode() const -
7925{ -
7926 return static_cast<const QPainterState *>(this)->bgMode; -
7927} -
7928 -
7929/*! -
7930 Returns the font in the current paint engine -
7931 state. -
7932 -
7933 This variable should only be used when the state() returns a -
7934 combination which includes the QPaintEngine::DirtyFont flag. -
7935 -
7936 \sa state(), QPaintEngine::updateState() -
7937*/ -
7938 -
7939QFont QPaintEngineState::font() const -
7940{ -
7941 return static_cast<const QPainterState *>(this)->font; -
7942} -
7943 -
7944/*! -
7945 \since 4.2 -
7946 \obsolete -
7947 -
7948 Returns the matrix in the current paint engine -
7949 state. -
7950 -
7951 \note It is advisable to use transform() instead of this function to -
7952 preserve the properties of perspective transformations. -
7953 -
7954 This variable should only be used when the state() returns a -
7955 combination which includes the QPaintEngine::DirtyTransform flag. -
7956 -
7957 \sa state(), QPaintEngine::updateState() -
7958*/ -
7959 -
7960QMatrix QPaintEngineState::matrix() const -
7961{ -
7962 const QPainterState *st = static_cast<const QPainterState *>(this); -
7963 -
7964 return st->matrix.toAffine(); -
7965} -
7966 -
7967/*! -
7968 \since 4.3 -
7969 -
7970 Returns the matrix in the current paint engine state. -
7971 -
7972 This variable should only be used when the state() returns a -
7973 combination which includes the QPaintEngine::DirtyTransform flag. -
7974 -
7975 \sa state(), QPaintEngine::updateState() -
7976*/ -
7977 -
7978 -
7979QTransform QPaintEngineState::transform() const -
7980{ -
7981 const QPainterState *st = static_cast<const QPainterState *>(this); -
7982 -
7983 return st->matrix; -
7984} -
7985 -
7986 -
7987/*! -
7988 Returns the clip operation in the current paint engine -
7989 state. -
7990 -
7991 This variable should only be used when the state() returns a -
7992 combination which includes either the QPaintEngine::DirtyClipPath -
7993 or the QPaintEngine::DirtyClipRegion flag. -
7994 -
7995 \sa state(), QPaintEngine::updateState() -
7996*/ -
7997 -
7998Qt::ClipOperation QPaintEngineState::clipOperation() const -
7999{ -
8000 return static_cast<const QPainterState *>(this)->clipOperation; -
8001} -
8002 -
8003/*! -
8004 \since 4.3 -
8005 -
8006 Returns whether the coordinate of the fill have been specified -
8007 as bounded by the current rendering operation and have to be -
8008 resolved (about the currently rendered primitive). -
8009*/ -
8010bool QPaintEngineState::brushNeedsResolving() const -
8011{ -
8012 const QBrush &brush = static_cast<const QPainterState *>(this)->brush; -
8013 return needsResolving(brush); -
8014} -
8015 -
8016 -
8017/*! -
8018 \since 4.3 -
8019 -
8020 Returns whether the coordinate of the stroke have been specified -
8021 as bounded by the current rendering operation and have to be -
8022 resolved (about the currently rendered primitive). -
8023*/ -
8024bool QPaintEngineState::penNeedsResolving() const -
8025{ -
8026 const QPen &pen = static_cast<const QPainterState *>(this)->pen; -
8027 return needsResolving(pen.brush()); -
8028} -
8029 -
8030/*! -
8031 Returns the clip region in the current paint engine state. -
8032 -
8033 This variable should only be used when the state() returns a -
8034 combination which includes the QPaintEngine::DirtyClipRegion flag. -
8035 -
8036 \sa state(), QPaintEngine::updateState() -
8037*/ -
8038 -
8039QRegion QPaintEngineState::clipRegion() const -
8040{ -
8041 return static_cast<const QPainterState *>(this)->clipRegion; -
8042} -
8043 -
8044/*! -
8045 Returns the clip path in the current paint engine state. -
8046 -
8047 This variable should only be used when the state() returns a -
8048 combination which includes the QPaintEngine::DirtyClipPath flag. -
8049 -
8050 \sa state(), QPaintEngine::updateState() -
8051*/ -
8052 -
8053QPainterPath QPaintEngineState::clipPath() const -
8054{ -
8055 return static_cast<const QPainterState *>(this)->clipPath; -
8056} -
8057 -
8058/*! -
8059 Returns whether clipping is enabled or not in the current paint -
8060 engine state. -
8061 -
8062 This variable should only be used when the state() returns a -
8063 combination which includes the QPaintEngine::DirtyClipEnabled -
8064 flag. -
8065 -
8066 \sa state(), QPaintEngine::updateState() -
8067*/ -
8068 -
8069bool QPaintEngineState::isClipEnabled() const -
8070{ -
8071 return static_cast<const QPainterState *>(this)->clipEnabled; -
8072} -
8073 -
8074/*! -
8075 Returns the render hints in the current paint engine state. -
8076 -
8077 This variable should only be used when the state() returns a -
8078 combination which includes the QPaintEngine::DirtyHints -
8079 flag. -
8080 -
8081 \sa state(), QPaintEngine::updateState() -
8082*/ -
8083 -
8084QPainter::RenderHints QPaintEngineState::renderHints() const -
8085{ -
8086 return static_cast<const QPainterState *>(this)->renderHints; -
8087} -
8088 -
8089/*! -
8090 Returns the composition mode in the current paint engine state. -
8091 -
8092 This variable should only be used when the state() returns a -
8093 combination which includes the QPaintEngine::DirtyCompositionMode -
8094 flag. -
8095 -
8096 \sa state(), QPaintEngine::updateState() -
8097*/ -
8098 -
8099QPainter::CompositionMode QPaintEngineState::compositionMode() const -
8100{ -
8101 return static_cast<const QPainterState *>(this)->composition_mode; -
8102} -
8103 -
8104 -
8105/*! -
8106 Returns a pointer to the painter currently updating the paint -
8107 engine. -
8108*/ -
8109 -
8110QPainter *QPaintEngineState::painter() const -
8111{ -
8112 return static_cast<const QPainterState *>(this)->painter; -
8113} -
8114 -
8115 -
8116/*! -
8117 \since 4.2 -
8118 -
8119 Returns the opacity in the current paint engine state. -
8120*/ -
8121 -
8122qreal QPaintEngineState::opacity() const -
8123{ -
8124 return static_cast<const QPainterState *>(this)->opacity; -
8125} -
8126 -
8127/*! -
8128 \since 4.3 -
8129 -
8130 Sets the world transformation matrix. -
8131 If \a combine is true, the specified \a transform is combined with -
8132 the current matrix; otherwise it replaces the current matrix. -
8133 -
8134 \sa transform(), setWorldTransform() -
8135*/ -
8136 -
8137void QPainter::setTransform(const QTransform &transform, bool combine ) -
8138{ -
8139 setWorldTransform(transform, combine); -
8140} -
8141 -
8142/*! -
8143 Returns the world transformation matrix. -
8144 -
8145 \sa worldTransform() -
8146*/ -
8147 -
8148const QTransform & QPainter::transform() const -
8149{ -
8150 return worldTransform(); -
8151} -
8152 -
8153 -
8154/*! -
8155 Returns the matrix that transforms from logical coordinates to -
8156 device coordinates of the platform dependent paint device. -
8157 -
8158 This function is \e only needed when using platform painting -
8159 commands on the platform dependent handle (Qt::HANDLE), and the -
8160 platform does not do transformations nativly. -
8161 -
8162 The QPaintEngine::PaintEngineFeature enum can be queried to -
8163 determine whether the platform performs the transformations or -
8164 not. -
8165 -
8166 \sa worldTransform(), QPaintEngine::hasFeature(), -
8167*/ -
8168 -
8169const QTransform & QPainter::deviceTransform() const -
8170{ -
8171 Q_D(const QPainter); -
8172 if (!d->engine) { -
8173 qWarning("QPainter::deviceTransform: Painter not active"); -
8174 return d->fakeState()->transform; -
8175 } -
8176 return d->state->matrix; -
8177} -
8178 -
8179 -
8180/*! -
8181 Resets any transformations that were made using translate(), -
8182 scale(), shear(), rotate(), setWorldTransform(), setViewport() -
8183 and setWindow(). -
8184 -
8185 \sa {Coordinate Transformations} -
8186*/ -
8187 -
8188void QPainter::resetTransform() -
8189{ -
8190 Q_D(QPainter); -
8191#ifdef QT_DEBUG_DRAW -
8192 if (qt_show_painter_debug_output) -
8193 printf("QPainter::resetMatrix()\n"); -
8194#endif -
8195 if (!d->engine) { -
8196 qWarning("QPainter::resetMatrix: Painter not active"); -
8197 return; -
8198 } -
8199 -
8200 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins -
8201 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth); -
8202 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight); -
8203 d->state->worldMatrix = QTransform(); -
8204 setMatrixEnabled(false); -
8205 setViewTransformEnabled(false); -
8206 if (d->extended) -
8207 d->extended->transformChanged(); -
8208 else -
8209 d->state->dirtyFlags |= QPaintEngine::DirtyTransform; -
8210} -
8211 -
8212/*! -
8213 Sets the world transformation matrix. -
8214 If \a combine is true, the specified \a matrix is combined with the current matrix; -
8215 otherwise it replaces the current matrix. -
8216 -
8217 \sa transform(), setTransform() -
8218*/ -
8219 -
8220void QPainter::setWorldTransform(const QTransform &matrix, bool combine ) -
8221{ -
8222 Q_D(QPainter); -
8223 -
8224 if (!d->engine) { -
8225 qWarning("QPainter::setWorldTransform: Painter not active"); -
8226 return; -
8227 } -
8228 -
8229 if (combine) -
8230 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines -
8231 else -
8232 d->state->worldMatrix = matrix; // set new matrix -
8233 -
8234 d->state->WxF = true; -
8235 d->updateMatrix(); -
8236} -
8237 -
8238/*! -
8239 Returns the world transformation matrix. -
8240*/ -
8241 -
8242const QTransform & QPainter::worldTransform() const -
8243{ -
8244 Q_D(const QPainter); -
8245 if (!d->engine) { -
8246 qWarning("QPainter::worldTransform: Painter not active"); -
8247 return d->fakeState()->transform; -
8248 } -
8249 return d->state->worldMatrix; -
8250} -
8251 -
8252/*! -
8253 Returns the transformation matrix combining the current -
8254 window/viewport and world transformation. -
8255 -
8256 \sa setWorldTransform(), setWindow(), setViewport() -
8257*/ -
8258 -
8259QTransform QPainter::combinedTransform() const -
8260{ -
8261 Q_D(const QPainter); -
8262 if (!d->engine) { -
8263 qWarning("QPainter::combinedTransform: Painter not active"); -
8264 return QTransform(); -
8265 } -
8266 return d->state->worldMatrix * d->viewTransform() * d->hidpiScaleTransform(); -
8267} -
8268 -
8269/*! -
8270 \since 4.7 -
8271 -
8272 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap, -
8273 at multiple positions with different scale, rotation and opacity. \a -
8274 fragments is an array of \a fragmentCount elements specifying the -
8275 parameters used to draw each pixmap fragment. The \a hints -
8276 parameter can be used to pass in drawing hints. -
8277 -
8278 This function is potentially faster than multiple calls to drawPixmap(), -
8279 since the backend can optimize state changes. -
8280 -
8281 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint -
8282*/ -
8283 -
8284void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, -
8285 const QPixmap &pixmap, PixmapFragmentHints hints) -
8286{ -
8287 Q_D(QPainter); -
8288 -
8289 if (!d->engine || pixmap.isNull()) -
8290 return; -
8291 -
8292#ifndef QT_NO_DEBUG -
8293 for (int i = 0; i < fragmentCount; ++i) { -
8294 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop, -
8295 fragments[i].width, fragments[i].height); -
8296 if (!(QRectF(pixmap.rect()).contains(sourceRect))) -
8297 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle"); -
8298 } -
8299#endif -
8300 -
8301 if (d->engine->isExtended()) { -
8302 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints); -
8303 } else { -
8304 qreal oldOpacity = opacity(); -
8305 QTransform oldTransform = transform(); -
8306 -
8307 for (int i = 0; i < fragmentCount; ++i) { -
8308 QTransform transform = oldTransform; -
8309 qreal xOffset = 0; -
8310 qreal yOffset = 0; -
8311 if (fragments[i].rotation == 0) { -
8312 xOffset = fragments[i].x; -
8313 yOffset = fragments[i].y; -
8314 } else { -
8315 transform.translate(fragments[i].x, fragments[i].y); -
8316 transform.rotate(fragments[i].rotation); -
8317 } -
8318 setOpacity(oldOpacity * fragments[i].opacity); -
8319 setTransform(transform); -
8320 -
8321 qreal w = fragments[i].scaleX * fragments[i].width; -
8322 qreal h = fragments[i].scaleY * fragments[i].height; -
8323 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop, -
8324 fragments[i].width, fragments[i].height); -
8325 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect); -
8326 } -
8327 -
8328 setOpacity(oldOpacity); -
8329 setTransform(oldTransform); -
8330 } -
8331} -
8332 -
8333/*! -
8334 \since 4.7 -
8335 \class QPainter::PixmapFragment -
8336 \inmodule QtGui -
8337 -
8338 \brief This class is used in conjunction with the -
8339 QPainter::drawPixmapFragments() function to specify how a pixmap, or -
8340 sub-rect of a pixmap, is drawn. -
8341 -
8342 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used -
8343 as a source rectangle within the pixmap passed into the -
8344 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a -
8345 width and \a height are used to calculate the target rectangle that is -
8346 drawn. \a x and \a y denotes the center of the target rectangle. The \a -
8347 width and \a height in the target rectangle is scaled by the \a scaleX and -
8348 \a scaleY values. The resulting target rectangle is then rotated \a -
8349 rotation degrees around the \a x, \a y center point. -
8350 -
8351 \sa QPainter::drawPixmapFragments() -
8352*/ -
8353 -
8354/*! -
8355 \since 4.7 -
8356 -
8357 This is a convenience function that returns a QPainter::PixmapFragment that is -
8358 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a -
8359 rotation, \a opacity parameters. -
8360*/ -
8361 -
8362QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect, -
8363 qreal scaleX, qreal scaleY, qreal rotation, -
8364 qreal opacity) -
8365{ -
8366 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(), -
8367 sourceRect.height(), scaleX, scaleY, rotation, opacity}; -
8368 return fragment; -
8369} -
8370 -
8371/*! -
8372 \variable QPainter::PixmapFragment::x -
8373 \brief the x coordinate of center point in the target rectangle. -
8374*/ -
8375 -
8376/*! -
8377 \variable QPainter::PixmapFragment::y -
8378 \brief the y coordinate of the center point in the target rectangle. -
8379*/ -
8380 -
8381/*! -
8382 \variable QPainter::PixmapFragment::sourceLeft -
8383 \brief the left coordinate of the source rectangle. -
8384*/ -
8385 -
8386/*! -
8387 \variable QPainter::PixmapFragment::sourceTop -
8388 \brief the top coordinate of the source rectangle. -
8389*/ -
8390 -
8391/*! -
8392 \variable QPainter::PixmapFragment::width -
8393 -
8394 \brief the width of the source rectangle and is used to calculate the width -
8395 of the target rectangle. -
8396*/ -
8397 -
8398/*! -
8399 \variable QPainter::PixmapFragment::height -
8400 -
8401 \brief the height of the source rectangle and is used to calculate the -
8402 height of the target rectangle. -
8403*/ -
8404 -
8405/*! -
8406 \variable QPainter::PixmapFragment::scaleX -
8407 \brief the horizontal scale of the target rectangle. -
8408*/ -
8409 -
8410/*! -
8411 \variable QPainter::PixmapFragment::scaleY -
8412 \brief the vertical scale of the target rectangle. -
8413*/ -
8414 -
8415/*! -
8416 \variable QPainter::PixmapFragment::rotation -
8417 -
8418 \brief the rotation of the target rectangle in degrees. The target -
8419 rectangle is rotated after it has been scaled. -
8420*/ -
8421 -
8422/*! -
8423 \variable QPainter::PixmapFragment::opacity -
8424 -
8425 \brief the opacity of the target rectangle, where 0.0 is fully transparent -
8426 and 1.0 is fully opaque. -
8427*/ -
8428 -
8429/*! -
8430 \since 4.7 -
8431 -
8432 \enum QPainter::PixmapFragmentHint -
8433 -
8434 \value OpaqueHint Indicates that the pixmap fragments to be drawn are -
8435 opaque. Opaque fragments are potentially faster to draw. -
8436 -
8437 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment -
8438*/ -
8439 -
8440void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation) -
8441{ -
8442 p->draw_helper(path, operation); -
8443} -
8444 -
8445QT_END_NAMESPACE -
8446 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial