/****************************************************************************
**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: http://www.qt-project.org/
+** 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);
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()
*/
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