/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** 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
-** 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.
+** 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, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** 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.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
+** 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$
#include "qstatictext.h"
#include "qglyphrun.h"
+#include <qpa/qplatformtheme.h>
+
#include <private/qfontengine_p.h>
#include <private/qpaintengine_p.h>
#include <private/qemulationpaintengine_p.h>
const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
int tabstops, int* tabarray, int tabarraylen,
QPainter *painter);
-static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
+static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
QTextCharFormat::UnderlineStyle underlineStyle,
QTextItem::RenderFlags flags, qreal width,
const QTextCharFormat &charFormat);
case QInternal::Printer:
case QInternal::Picture:
// can be drawn onto these devices safely from any thread
-#ifndef Q_WS_WIN
if (extraCondition)
-#endif
break;
default:
-#ifdef Q_WS_X11
- if (QApplication::testAttribute(Qt::AA_X11InitThreads))
- return true;
-#endif
if (!extraCondition && QThread::currentThread() != qApp->thread()) {
qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
return false;
if (!newState) {
engine->state = newState;
-
} else if (newState->state() || engine->state!=newState) {
- bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
- && newState->pen.widthF() == 0;
- if (setNonCosmeticPen) {
- // Override the default pen's cosmetic state if the
- // NonCosmeticDefaultPen render hint is used.
- QPen oldPen = newState->pen;
- newState->pen.setWidth(1);
- newState->pen.setCosmetic(false);
- newState->dirtyFlags |= QPaintEngine::DirtyPen;
-
- updateStateImpl(newState);
-
- // Restore the state pen back to its default to preserve visible
- // state.
- newState->pen = oldPen;
- } else {
- updateStateImpl(newState);
- }
+ updateStateImpl(newState);
}
}
\brief The QPainter class performs low-level painting on widgets and
other paint devices.
+ \inmodule QtGui
\ingroup painting
\reentrant
painter. Then draw. Remember to destroy the QPainter object after
drawing. For example:
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
+ \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
\warning When the paintdevice is a widget, QPainter can only be
used inside a paintEvent() function or in a function called by
- paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
- widget attribute is set. On Mac OS X and Windows, you can only
- paint in a paintEvent() function regardless of this attribute's
- setting.
+ paintEvent().
\tableofcontents
\list
- \o font() is the font used for drawing text. If the painter
+ \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.
- \o brush() defines the color or pattern that is used for filling
+ \li brush() defines the color or pattern that is used for filling
shapes.
- \o pen() defines the color or stipple that is used for drawing
+ \li pen() defines the color or stipple that is used for drawing
lines or boundaries.
- \o backgroundMode() defines whether there is a background() or
+ \li backgroundMode() defines whether there is a background() or
not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
- \o background() only applies when backgroundMode() is \l
+ \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.
- \o brushOrigin() defines the origin of the tiled brushes, normally
+ \li brushOrigin() defines the origin of the tiled brushes, normally
the origin of widget's background.
- \o viewport(), window(), worldTransform() make up the painter's coordinate
+ \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.
- \o hasClipping() tells whether the painter clips at all. (The paint
+ \li hasClipping() tells whether the painter clips at all. (The paint
device clips, too.) If the painter clips, it clips to clipRegion().
- \o layoutDirection() defines the layout direction used by the
+ \li layoutDirection() defines the layout direction used by the
painter when drawing text.
- \o worldMatrixEnabled() tells whether world transformation is enabled.
+ \li worldMatrixEnabled() tells whether world transformation is enabled.
- \o viewTransformEnabled() tells whether view transformation is
+ \li viewTransformEnabled() tells whether view transformation is
enabled.
\endlist
\table 100%
\row
- \o \inlineimage qpainter-basicdrawing.png
- \o
- \bold {Basic Drawing Example}
+ \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
\table 100%
\row
- \o
- \bold {Painter Paths example}
+ \li
+ \b {Painter Paths example}
The QPainterPath class provides a container for painting
operations, enabling graphical shapes to be constructed and
The \l {painting/painterpaths}{Painter Paths} example shows how
painter paths can be used to build complex shapes for rendering.
- \o \inlineimage qpainter-painterpaths.png
+ \li \inlineimage qpainter-painterpaths.png
\endtable
QPainter also provides the fillPath() function which fills the
\table
\header
- \o \l {painting/deform}{Vector Deformation}
- \o \l {painting/gradients}{Gradients}
- \o \l {painting/pathstroke}{Path Stroking}
+ \li \l {painting/deform}{Vector Deformation}
+ \li \l {painting/gradients}{Gradients}
+ \li \l {painting/pathstroke}{Path Stroking}
\row
- \o \inlineimage qpainter-vectordeformation.png
- \o \inlineimage qpainter-gradients.png
- \o \inlineimage qpainter-pathstroking.png
+ \li \inlineimage qpainter-vectordeformation.png
+ \li \inlineimage qpainter-gradients.png
+ \li \inlineimage qpainter-pathstroking.png
\endtable
\table 100%
\row
- \o \inlineimage qpainter-concentriccircles.png
- \o
- \bold {Concentric Circles Example}
+ \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
\table
\header
- \o nop \o rotate() \o scale() \o translate()
+ \li nop \li rotate() \li scale() \li translate()
\row
- \o \inlineimage qpainter-clock.png
- \o \inlineimage qpainter-rotation.png
- \o \inlineimage qpainter-scale.png
- \o \inlineimage qpainter-translation.png
+ \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,
\table 100%
\row
- \o
- \bold {Affine Transformations Example}
+ \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.
- \o \inlineimage qpainter-affinetransformations.png
+ \li \inlineimage qpainter-affinetransformations.png
\endtable
All the tranformation operations operate on the transformation
\table 100%
\row
- \o \inlineimage qpainter-compositiondemo.png
+ \li \inlineimage qpainter-compositiondemo.png
- \o
- \bold {Composition Modes Example}
+ \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
\list
- \o Raster - This backend implements all rendering in pure software
+ \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.
- \o OpenGL 2.0 (ES) - This backend is the primary backend for
+ \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
onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the
command line when the underlying system supports it.
- \o OpenVG - This backend implements the Khronos standard for 2D
+ \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
\list
- \o Simple transformations, meaning translation and scaling, pluss
+ \li Simple transformations, meaning translation and scaling, pluss
0, 90, 180, 270 degree rotations.
- \o \c drawPixmap() in combination with simple transformations and
+ \li \c drawPixmap() in combination with simple transformations and
opacity with non-smooth transformation mode
(\c QPainter::SmoothPixmapTransform not enabled as a render hint).
- \o Rectangle fills with solid color, two-color linear gradients
+ \li Rectangle fills with solid color, two-color linear gradients
and simple transforms.
- \o Rectangular clipping with simple transformations and intersect
+ \li Rectangular clipping with simple transformations and intersect
clip.
- \o Composition Modes \c QPainter::CompositionMode_Source and
+ \li Composition Modes \c QPainter::CompositionMode_Source and
QPainter::CompositionMode_SourceOver
- \o Rounded rectangle filling using solid color and two-color
+ \li Rounded rectangle filling using solid color and two-color
linear gradients fills.
- \o 3x3 patched pixmaps, via qDrawBorderPixmap.
+ \li 3x3 patched pixmaps, via qDrawBorderPixmap.
\endlist
indicating that the engine should use fragment programs and offscreen
rendering for antialiasing.
- \value NonCosmeticDefaultPen The engine should interpret pens with a width
- of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
- pen with a width of 1.
+ \value NonCosmeticDefaultPen This value is obsolete, the default for QPen
+ is now non-cosmetic.
+
+ \value Qt4CompatiblePainting Compatibility hint telling the engine to use the
+ same X11 based fill rules as in Qt 4, where aliased rendering is offset
+ by slightly less than half a pixel. Also will treat default constructed pens
+ as cosmetic. Potentially useful when porting a Qt 4 application to Qt 5.
\sa renderHints(), setRenderHint(), {QPainter#Rendering
Quality}{Rendering Quality}, {Concentric Circles Example}
automatically calls end().
Here's an example using begin() and end():
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
+ \snippet code/src_gui_painting_qpainter.cpp 1
The same example using this constructor:
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
+ \snippet code/src_gui_painting_qpainter.cpp 2
Since the constructor cannot provide feedback when the initialization
of the painter failed you should rather use begin() and end() to paint
/*!
Initializes the painters pen, background and font to the same as
- the given \a paint device.
+ the given \a device.
\obsolete
return;
}
- device->init(this);
+ device->initPainter(this);
if (d->extended) {
d->extended->penChanged();
The errors that can occur are serious problems, such as these:
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
+ \snippet code/src_gui_painting_qpainter.cpp 3
Note that most of the time, you can use one of the constructors
instead of begin(), and that end() is automatically done at
d->engine->state = d->state;
switch (pd->devType()) {
-#if 0
- // is this needed any more??
- case QInternal::Widget:
- {
- const QWidget *widget = static_cast<const QWidget *>(pd);
- Q_ASSERT(widget);
-
- const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
- const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
-
- // Adjust offset for alien widgets painting outside the paint event.
- if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
- && widget->testAttribute(Qt::WA_WState_Created)) {
- const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
- d->state->redirectionMatrix.translate(offset.x(), offset.y());
- }
- break;
- }
-#endif
case QInternal::Pixmap:
{
QPixmap *pm = static_cast<QPixmap *>(pd);
2 engine:
\list
- \i blending is disabled
- \i the depth, stencil and scissor tests are disabled
- \i the active texture unit is reset to 0
- \i the depth mask, depth function and the clear depth are reset to their
+ \li blending is disabled
+ \li the depth, stencil and scissor tests are disabled
+ \li the active texture unit is reset to 0
+ \li the depth mask, depth function and the clear depth are reset to their
default values
- \i the stencil mask, stencil operation and stencil function are reset to
+ \li the stencil mask, stencil operation and stencil function are reset to
their default values
- \i the current color is reset to solid white
+ \li the current color is reset to solid white
\endlist
If, for example, the OpenGL polygon mode is changed by the user inside a
default state by endNativePainting(). Here is an example that shows
intermixing of painter commands and raw OpenGL commands:
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
+ \snippet code/src_gui_painting_qpainter.cpp 21
\sa endNativePainting()
*/
source defines the translucency of the pixel.
When the paint device is a QImage, the image format must be set to
- \l {QImage::Format}{Format_ARGB32Premultiplied} or
+ \l {QImage::Format}{Format_ARGB32_Premultiplied} or
\l {QImage::Format}{Format_ARGB32} for the composition modes to have
any effect. For performance the premultiplied version is the preferred
format.
where the source is AND'ed with the inverted destination pixels
(src AND (NOT dst)).
+ \value RasterOp_NotSourceOrDestination Does a bitwise operation
+ where the source is inverted and then OR'ed with the destination
+ ((NOT src) OR dst).
+
+ \value RasterOp_ClearDestination The pixels in the destination are
+ cleared (set to 0) independent of the source.
+
+ \value RasterOp_SetDestination The pixels in the destination are
+ set (set to 1) independent of the source.
+
+ \value RasterOp_NotDestination Does a bitwise operation
+ where the destination pixels are inverted (NOT dst).
+
+ \value RasterOp_SourceOrNotDestination Does a bitwise operation
+ where the source is OR'ed with the inverted destination pixels
+ (src OR (NOT dst)).
+
\sa compositionMode(), setCompositionMode(), {QPainter#Composition
Modes}{Composition Modes}, {Image Composition Example}
*/
The following functions can transform the coordinate system without using
a QMatrix:
\list
- \i translate()
- \i scale()
- \i shear()
- \i rotate()
+ \li translate()
+ \li scale()
+ \li shear()
+ \li rotate()
\endlist
They operate on the painter's worldMatrix() and are implemented like this:
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
+ \snippet code/src_gui_painting_qpainter.cpp 4
Note that when using setWorldMatrix() function you should always have
\a combine be true when you are drawing into a QPicture. Otherwise
/*!
Scales the coordinate system by (\a{sx}, \a{sy}).
- \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
- Transformations}
+ \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
*/
void QPainter::scale(qreal sx, qreal sy)
/*!
Shears the coordinate system by (\a{sh}, \a{sv}).
- \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
- Transformations}
+ \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
*/
void QPainter::shear(qreal sh, qreal sv)
/*!
\fn void QPainter::rotate(qreal angle)
- Rotates the coordinate system the given \a angle clockwise.
+ Rotates the coordinate system clockwise. The given \a angle parameter uses degree unit.
- \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
- Transformations}
+ \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
*/
void QPainter::rotate(qreal a)
Translates the coordinate system by the given \a offset; i.e. the
given \a offset is added to points.
- \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
- Transformations}
+ \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
*/
void QPainter::translate(const QPointF &offset)
{
\table 100%
\row
- \o \inlineimage qpainter-path.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
+ \li \inlineimage qpainter-path.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 5
\endtable
\sa {painting/painterpaths}{the Painter Paths
\table 100%
\row
- \o \inlineimage qpainter-line.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
+ \li \inlineimage qpainter-line.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 6
\endtable
\sa drawLines(), drawPolyline(), {Coordinate System}
\table 100%
\row
- \o \inlineimage qpainter-rectangle.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
+ \li \inlineimage qpainter-rectangle.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 7
\endtable
\sa drawRects(), drawPolygon(), {Coordinate System}
return;
}
- if (d->state->pen.style() == Qt::SolidLine
- && d->state->pen.widthF() == 0
- && d->state->pen.isSolid()
- && d->state->pen.color() == color)
- return;
+ QPen pen(color.isValid() ? color : QColor(Qt::black));
- QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
+ if (d->state->pen == pen)
+ return;
d->state->pen = pen;
if (d->extended)
/*!
\overload
- Sets the painter's pen to have the given \a style, width 0 and
+ Sets the painter's pen to have the given \a style, width 1 and
black color.
*/
return;
}
- if (d->state->pen.style() == style
- && (style == Qt::NoPen || (d->state->pen.widthF() == 0
- && d->state->pen.isSolid()
- && d->state->pen.color() == QColor(Qt::black))))
+ QPen pen = QPen(style);
+
+ if (d->state->pen == pen)
return;
- // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
- // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
- d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
+ d->state->pen = pen;
if (d->extended)
d->extended->penChanged();
\table 100%
\row
- \o \inlineimage qpainter-roundrect.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
+ \li \inlineimage qpainter-roundrect.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 8
\endtable
\sa drawRect(), QPen
\table 100%
\row
- \o \inlineimage qpainter-ellipse.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
+ \li \inlineimage qpainter-ellipse.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 9
\endtable
\sa drawPie(), {Coordinate System}
\table 100%
\row
- \o \inlineimage qpainter-arc.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
+ \li \inlineimage qpainter-arc.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 10
\endtable
\sa drawPie(), drawChord(), {Coordinate System}
/*!
\fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
- Draws a pie defined by the given \a rectangle, \a startAngle and
- and \a spanAngle.
+ Draws a pie defined by the given \a rectangle, \a startAngle and \a spanAngle.
The pie is filled with the current brush().
\table 100%
\row
- \o \inlineimage qpainter-pie.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
+ \li \inlineimage qpainter-pie.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 11
\endtable
\sa drawEllipse(), drawChord(), {Coordinate System}
\table 100%
\row
- \o \inlineimage qpainter-chord.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
+ \li \inlineimage qpainter-chord.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 12
\endtable
\sa drawArc(), drawPie(), {Coordinate System}
\table 100%
\row
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 13
\endtable
\sa drawLines(), drawPolygon(), {Coordinate System}
\table 100%
\row
- \o \inlineimage qpainter-polygon.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
+ \li \inlineimage qpainter-polygon.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 14
\endtable
The first point is implicitly connected to the last point, and the
\l{Qt::FillRule} for a more detailed description of these fill
rules.
- \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
+ \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
*/
void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
{
\table 100%
\row
- \o \inlineimage qpainter-polygon.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
+ \li \inlineimage qpainter-polygon.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 15
\endtable
The first point is implicitly connected to the last point, and the
\table 100%
\row
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 16
\endtable
If \a pixmap is a QBitmap it is drawn with the bits that are "set"
QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
QRawFontPrivate *fontD = QRawFontPrivate::get(font);
- bool supportsTransformations;
- if (d->extended != 0) {
- supportsTransformations = d->extended->supportsTransformations(fontD->fontEngine->fontDef.pixelSize,
- d->state->matrix);
- } else {
- supportsTransformations = d->engine->type() == QPaintEngine::CoreGraphics
- || d->state->matrix.isAffine();
- }
+ bool supportsTransformations = d->extended
+ ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
+ : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
for (int i=0; i<count; ++i) {
QPointF processedPosition = position + glyphPositions[i];
QVarLengthArray<QFixed, 128> advances(glyphCount);
QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
- qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
- qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
- qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
+ memset(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
+ memset(advances.data(), 0, advances.size() * sizeof(QFixed));
+ memset(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
textItem.glyphs.numGlyphs = glyphCount;
textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
fontEngine,
+ 0, // textEngine
(underline
? QTextCharFormat::SingleUnderline
: QTextCharFormat::NoUnderline),
Draws the given \a text with the currently defined text direction,
beginning at the given \a position.
- This function does not handle the newline character (\n), as it cannot
+ This function does not handle the newline character (\\n), as it cannot
break text into multiple lines, and it cannot display the newline character.
Use the QPainter::drawText() overload that takes a rectangle instead
if you want to draw multiple lines of text with the newline character, or
By default, QPainter draws text anti-aliased.
\note The y-position is used as the baseline of the font.
+
+ \sa setFont(), setPen()
*/
void QPainter::drawText(const QPointF &p, const QString &str)
return;
}
- bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.pixelSize(),
+ QFontEngine *fe = staticText_d->font.d->engineForScript(QUnicodeTables::Common);
+ if (fe->type() == QFontEngine::Multi)
+ fe = static_cast<QFontEngineMulti *>(fe)->engine(0);
+ bool supportsTransformations = d->extended->supportsTransformations(fe,
d->state->matrix);
if (supportsTransformations && !staticText_d->untransformedCoordinates) {
staticText_d->untransformedCoordinates = true;
\note The y-position is used as the baseline of the font.
+ \sa setFont(), setPen()
*/
/*!
\overload
Draws the given \a text within the provided \a rectangle.
+ The \a rectangle along with alignment \a flags defines the anchors for the \a text.
\table 100%
\row
- \o \inlineimage qpainter-text.png
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
+ \li \inlineimage qpainter-text.png
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 17
\endtable
The \a boundingRect (if not null) is set to the what the bounding rectangle
OR of the following flags:
\list
- \o Qt::AlignLeft
- \o Qt::AlignRight
- \o Qt::AlignHCenter
- \o Qt::AlignJustify
- \o Qt::AlignTop
- \o Qt::AlignBottom
- \o Qt::AlignVCenter
- \o Qt::AlignCenter
- \o Qt::TextDontClip
- \o Qt::TextSingleLine
- \o Qt::TextExpandTabs
- \o Qt::TextShowMnemonic
- \o Qt::TextWordWrap
- \o Qt::TextIncludeTrailingSpaces
+ \li Qt::AlignLeft
+ \li Qt::AlignRight
+ \li Qt::AlignHCenter
+ \li Qt::AlignJustify
+ \li Qt::AlignTop
+ \li Qt::AlignBottom
+ \li Qt::AlignVCenter
+ \li Qt::AlignCenter
+ \li Qt::TextDontClip
+ \li Qt::TextSingleLine
+ \li Qt::TextExpandTabs
+ \li Qt::TextShowMnemonic
+ \li Qt::TextWordWrap
+ \li Qt::TextIncludeTrailingSpaces
\endlist
\sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
By default, QPainter draws text anti-aliased.
\note The y-coordinate of \a rectangle is used as the top of the font.
+
+ \sa setFont(), setPen()
*/
/*!
\note The y-position is used as the baseline of the font.
+ \sa setFont(), setPen()
*/
/*!
the following flags:
\list
- \o Qt::AlignLeft
- \o Qt::AlignRight
- \o Qt::AlignHCenter
- \o Qt::AlignJustify
- \o Qt::AlignTop
- \o Qt::AlignBottom
- \o Qt::AlignVCenter
- \o Qt::AlignCenter
- \o Qt::TextSingleLine
- \o Qt::TextExpandTabs
- \o Qt::TextShowMnemonic
- \o Qt::TextWordWrap
+ \li Qt::AlignLeft
+ \li Qt::AlignRight
+ \li Qt::AlignHCenter
+ \li Qt::AlignJustify
+ \li Qt::AlignTop
+ \li Qt::AlignBottom
+ \li Qt::AlignVCenter
+ \li Qt::AlignCenter
+ \li Qt::TextSingleLine
+ \li Qt::TextExpandTabs
+ \li Qt::TextShowMnemonic
+ \li Qt::TextWordWrap
\endlist
By default, QPainter draws text anti-aliased.
\note The y-position is used as the top of the font.
- \sa Qt::AlignmentFlag, Qt::TextFlag
+ \sa Qt::AlignmentFlag, Qt::TextFlag, setFont(), setPen()
*/
/*!
By default, QPainter draws text anti-aliased.
\note The y-coordinate of \a rectangle is used as the top of the font.
+
+ \sa setFont(), setPen()
*/
void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
{
{
const qreal radiusBase = qMax(qreal(1), maxRadius);
- QString key = QLatin1Literal("WaveUnderline-")
+ QString key = QLatin1String("WaveUnderline-")
% pen.color().name()
% HexString<qreal>(radiusBase);
return pixmap;
}
-static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
+static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
QTextCharFormat::UnderlineStyle underlineStyle,
QTextItem::RenderFlags flags, qreal width,
const QTextCharFormat &charFormat)
const qreal underlineOffset = fe->underlinePosition().toReal();
// deliberately ceil the offset to avoid the underline coming too close to
// the text above it.
- const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
- const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
+ const qreal underlinePos = pos.y() + qCeil(underlineOffset);
if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
- underlineStyle = QTextCharFormat::SpellCheckUnderline; // ### Qt5 QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
+ QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
+ if (theme)
+ underlineStyle = QTextCharFormat::UnderlineStyle(theme->themeHint(QPlatformTheme::SpellCheckUnderlineStyle).toInt());
}
if (underlineStyle == QTextCharFormat::WaveUnderline) {
painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
painter->restore();
} else if (underlineStyle != QTextCharFormat::NoUnderline) {
- QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
-
QColor uc = charFormat.underlineColor();
if (uc.isValid())
pen.setColor(uc);
pen.setStyle((Qt::PenStyle)(underlineStyle));
painter->setPen(pen);
- painter->drawLine(underLine);
+ QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos);
+ if (textEngine)
+ textEngine->addUnderline(painter, underline);
+ else
+ painter->drawLine(underline);
}
pen.setStyle(Qt::SolidLine);
QLineF strikeOutLine = line;
strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
painter->setPen(pen);
- painter->drawLine(strikeOutLine);
+ if (textEngine)
+ textEngine->addStrikeOut(painter, strikeOutLine);
+ else
+ painter->drawLine(strikeOutLine);
}
if (flags & QTextItem::Overline) {
- QLineF overLine = line;
- overLine.translate(0., - fe->ascent().toReal());
+ QLineF overline = line;
+ overline.translate(0., - fe->ascent().toReal());
painter->setPen(pen);
- painter->drawLine(overLine);
+ if (textEngine)
+ textEngine->addOverline(painter, overline);
+ else
+ painter->drawLine(overline);
}
painter->setPen(oldPen);
// We don't support glyphs that do not share a common baseline. If this turns out to
// be a relevant use case, then we need to find clusters of glyphs that share a baseline
- // and do a drawTextItemDecorations call per cluster.
+ // and do a drawTextItemDecoration call per cluster.
if (i == 0 || baseLine < positions[i].y)
baseLine = positions[i].y;
drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
fontEngine,
+ 0, // textEngine
font.underline() ? QTextCharFormat::SingleUnderline
: QTextCharFormat::NoUnderline, flags,
width.toReal(), charFormat);
}
-void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
+void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
+{
+ Q_D(QPainter);
+
+ d->drawTextItem(p, ti, static_cast<QTextEngine *>(0));
+}
+
+void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine)
{
#ifdef QT_DEBUG_DRAW
if (qt_show_painter_debug_output)
p.x(), p.y(), qPrintable(_ti.text()));
#endif
- Q_D(QPainter);
+ Q_Q(QPainter);
- if (!d->engine)
+ if (!engine)
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(),
+ qt_painter_thread_test(device->devType(),
"text and fonts",
QFontDatabase::supportsThreadedFontRendering());
#endif
QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
- if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
+ if (!extended && state->bgMode == Qt::OpaqueMode) {
QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
- fillRect(rect, d->state->bgBrush);
+ q->fillRect(rect, state->bgBrush);
}
- if (pen().style() == Qt::NoPen)
+ if (q->pen().style() == Qt::NoPen)
return;
- const RenderHints oldRenderHints = d->state->renderHints;
- if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
+ const QPainter::RenderHints oldRenderHints = state->renderHints;
+ if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) {
// draw antialias decoration (underline/overline/strikeout) with
// transformed text
bool aa = true;
- const QTransform &m = d->state->matrix;
- if (d->state->matrix.type() < QTransform::TxShear) {
+ const QTransform &m = state->matrix;
+ if (state->matrix.type() < QTransform::TxShear) {
bool isPlain90DegreeRotation =
(qFuzzyIsNull(m.m11())
&& qFuzzyIsNull(m.m12() - qreal(1))
aa = !isPlain90DegreeRotation;
}
if (aa)
- setRenderHint(QPainter::Antialiasing, true);
+ q->setRenderHint(QPainter::Antialiasing, true);
}
- if (!d->extended)
- d->updateState(d->state);
+ if (!extended)
+ updateState(state);
if (!ti.glyphs.numGlyphs) {
// nothing to do
if (rtl)
x -= ti2.width.toReal();
- d->engine->drawTextItem(QPointF(x, y), ti2);
+ engine->drawTextItem(QPointF(x, y), ti2);
if (!rtl)
x += ti2.width.toReal();
if (rtl)
x -= ti2.width.toReal();
- if (d->extended)
- d->extended->drawTextItem(QPointF(x, y), ti2);
+ if (extended)
+ extended->drawTextItem(QPointF(x, y), ti2);
else
- d->engine->drawTextItem(QPointF(x,y), ti2);
+ engine->drawTextItem(QPointF(x,y), ti2);
// reset the high byte for all glyphs
const int hi = which << 24;
glyphs.glyphs[i] = hi | glyphs.glyphs[i];
} else {
- if (d->extended)
- d->extended->drawTextItem(p, ti);
+ if (extended)
+ extended->drawTextItem(p, ti);
else
- d->engine->drawTextItem(p, ti);
+ engine->drawTextItem(p, ti);
}
- drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
- ti.charFormat);
+ drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle,
+ ti.flags, ti.width.toReal(), ti.charFormat);
- if (d->state->renderHints != oldRenderHints) {
- d->state->renderHints = oldRenderHints;
- if (d->extended)
- d->extended->renderHintsChanged();
+ if (state->renderHints != oldRenderHints) {
+ state->renderHints = oldRenderHints;
+ if (extended)
+ extended->renderHintsChanged();
else
- d->state->dirtyFlags |= QPaintEngine::DirtyHints;
+ state->dirtyFlags |= QPaintEngine::DirtyHints;
}
}
The \a flags argument is a bitwise OR of the following flags:
\list
- \o Qt::AlignLeft
- \o Qt::AlignRight
- \o Qt::AlignHCenter
- \o Qt::AlignTop
- \o Qt::AlignBottom
- \o Qt::AlignVCenter
- \o Qt::AlignCenter
- \o Qt::TextSingleLine
- \o Qt::TextExpandTabs
- \o Qt::TextShowMnemonic
- \o Qt::TextWordWrap
- \o Qt::TextIncludeTrailingSpaces
+ \li Qt::AlignLeft
+ \li Qt::AlignRight
+ \li Qt::AlignHCenter
+ \li Qt::AlignTop
+ \li Qt::AlignBottom
+ \li Qt::AlignVCenter
+ \li Qt::AlignCenter
+ \li Qt::TextSingleLine
+ \li Qt::TextExpandTabs
+ \li Qt::TextShowMnemonic
+ \li Qt::TextWordWrap
+ \li Qt::TextIncludeTrailingSpaces
\endlist
If several of the horizontal or several of the vertical alignment
flags are set, the resulting alignment is undefined.
\table 100%
\row
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 18
\endtable
\sa QPicture::play()
Erases the area inside the given \a rectangle. Equivalent to
calling
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
+ \snippet code/src_gui_painting_qpainter.cpp 19
\sa fillRect()
*/
The default viewport rectangle is the same as the device's
rectangle.
- \sa viewport(), viewTransformEnabled() {Coordinate
+ \sa viewport(), viewTransformEnabled(), {Coordinate
System#Window-Viewport Conversion}{Window-Viewport Conversion}
*/
const QPoint &offset)
{
Q_ASSERT(device != 0);
+ Q_UNUSED(device)
Q_UNUSED(replacement)
Q_UNUSED(offset)
qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
for (int i = 0; i < textLayout.lineCount(); i++) {
QTextLine line = textLayout.lineAt(i);
+ QTextEngine *eng = textLayout.engine();
+ eng->enableDelayDecorations();
qreal advance = line.horizontalAdvance();
xoff = 0;
if (tf & Qt::AlignRight) {
- QTextEngine *eng = textLayout.engine();
xoff = r.width() - advance -
eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
}
xoff = (r.width() - advance) / 2;
line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
+ eng->drawDecorations(painter);
}
if (restore) {
\table 100%
\row
- \o
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
+ \li
+ \snippet code/src_gui_painting_qpainter.cpp 20
\endtable
\sa drawPixmap()
/*!
\class QPaintEngineState
\since 4.1
+ \inmodule QtGui
\brief The QPaintEngineState class provides information about the
active paint engine's current state.
\target GetFunction
\table
- \header \o Property Flag \o Current Property Value
- \row \o QPaintEngine::DirtyBackground \o backgroundBrush()
- \row \o QPaintEngine::DirtyBackgroundMode \o backgroundMode()
- \row \o QPaintEngine::DirtyBrush \o brush()
- \row \o QPaintEngine::DirtyBrushOrigin \o brushOrigin()
- \row \o QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
- \o clipOperation()
- \row \o QPaintEngine::DirtyClipPath \o clipPath()
- \row \o QPaintEngine::DirtyClipRegion \o clipRegion()
- \row \o QPaintEngine::DirtyCompositionMode \o compositionMode()
- \row \o QPaintEngine::DirtyFont \o font()
- \row \o QPaintEngine::DirtyTransform \o transform()
- \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled()
- \row \o QPaintEngine::DirtyPen \o pen()
- \row \o QPaintEngine::DirtyHints \o renderHints()
+ \header \li Property Flag \li Current Property Value
+ \row \li QPaintEngine::DirtyBackground \li backgroundBrush()
+ \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode()
+ \row \li QPaintEngine::DirtyBrush \li brush()
+ \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin()
+ \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
+ \li clipOperation()
+ \row \li QPaintEngine::DirtyClipPath \li clipPath()
+ \row \li QPaintEngine::DirtyClipRegion \li clipRegion()
+ \row \li QPaintEngine::DirtyCompositionMode \li compositionMode()
+ \row \li QPaintEngine::DirtyFont \li font()
+ \row \li QPaintEngine::DirtyTransform \li transform()
+ \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled()
+ \row \li QPaintEngine::DirtyPen \li pen()
+ \row \li QPaintEngine::DirtyHints \li renderHints()
\endtable
The QPaintEngineState class also provide the painter() function
If \a combine is true, the specified \a transform is combined with
the current matrix; otherwise it replaces the current matrix.
- \sa transform() setWorldTransform()
+ \sa transform(), setWorldTransform()
*/
void QPainter::setTransform(const QTransform &transform, bool combine )
/*!
\since 4.7
\class QPainter::PixmapFragment
+ \inmodule QtGui
\brief This class is used in conjunction with the
QPainter::drawPixmapFragments() function to specify how a pixmap, or