/****************************************************************************
**
-** 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 "qpixmapcache.h"
#include "qpolygon.h"
#include "qtextlayout.h"
-#include "qwidget.h"
-#include "qapplication.h"
-#include "qstyle.h"
#include "qthread.h"
#include "qvarlengtharray.h"
#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>
#include <private/qpainterpath_p.h>
#include <private/qtextengine_p.h>
-#include <private/qwidget_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qmath_p.h>
#include <private/qstatictext_p.h>
#include <private/qglyphrun_p.h>
-#include <private/qstylehelper_p.h>
+#include <private/qhexstring_p.h>
+#include <private/qguiapplication_p.h>
#include <private/qrawfont_p.h>
QT_BEGIN_NAMESPACE
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;
Q_ASSERT(q);
Q_ASSERT(pdev);
- if (pdev->devType() != QInternal::Widget)
- return false;
-
- QWidget *widget = static_cast<QWidget *>(pdev);
- Q_ASSERT(widget);
-
- // Someone either called QPainter::setRedirected in the widget's paint event
- // right before this painter was created (or begin was called) or
- // sent a paint event directly to the widget.
- if (!widget->d_func()->redirectDev)
- return false;
-
- QPainter *sp = widget->d_func()->sharedPainter();
- if (!sp || !sp->isActive())
- return false;
-
- if (sp->paintEngine()->paintDevice() != widget->d_func()->redirectDev)
- return false;
-
- // Check if we're attempting to paint outside a paint event.
- if (!sp->d_ptr->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
- && !widget->testAttribute(Qt::WA_PaintOutsidePaintEvent)
- && !widget->testAttribute(Qt::WA_WState_InPaintEvent)) {
-
- qWarning("QPainter::begin: Widget painting can only begin as a result of a paintEvent");
+ QPainter *sp = pdev->sharedPainter();
+ if (!sp)
return false;
- }
// Save the current state of the shared painter and assign
// the current d_ptr to the shared painter's d_ptr.
Q_ASSERT(q->d_ptr->state);
// Now initialize the painter with correct widget properties.
- q->initFrom(widget);
+ q->initFrom(pdev);
QPoint offset;
- widget->d_func()->redirected(&offset);
+ pdev->redirected(&offset);
offset += q->d_ptr->engine->coordinateOffset();
// Update system rect.
- q->d_ptr->state->ww = q->d_ptr->state->vw = widget->width();
- q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
+ q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
+ q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
// Update matrix.
if (q->d_ptr->state->WxF) {
q->d_ptr->updateMatrix();
QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
- if (enginePrivate->currentClipWidget == widget) {
+ if (enginePrivate->currentClipDevice == pdev) {
enginePrivate->systemStateChanged();
return true;
}
// Update system transform and clip.
- enginePrivate->currentClipWidget = widget;
+ enginePrivate->currentClipDevice = pdev;
enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
return true;
}
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
function that draws the outline of the given path (i.e. strokes
the path).
- See also the \l {demos/deform}{Vector Deformation} demo which
+ 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 {demos/gradients}{Gradients} demo which shows
+ QPainterPath, the \l {painting/gradients}{Gradients} example which shows
the different types of gradients that are available in Qt, and the \l
- {demos/pathstroke}{Path Stroking} demo which shows Qt's built-in
+ {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
- \o \l {demos/deform}{Vector Deformation}
- \o \l {demos/gradients}{Gradients}
- \o \l {demos/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 Demo}
+ \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 also used by default on Windows and on
- QWS. It can be used as default graphics system on any
- OS/hardware/software combination by passing \c {-graphicssystem
- raster} on the command line
+ 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
last couple of years. The engine can be enabled by using QPainter
- onto a QGLWidget or by passing \c {-graphicssystem opengl} on 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
QPaintDevice *QPainter::device() const
{
Q_D(const QPainter);
- if (isActive() && d->engine->d_func()->currentClipWidget)
- return d->engine->d_func()->currentClipWidget;
+ if (isActive() && d->engine->d_func()->currentClipDevice)
+ return d->engine->d_func()->currentClipDevice;
return d->original_device;
}
/*!
Initializes the painters pen, background and font to the same as
- the given \a widget. This function is called automatically when the
- painter is opened on a QWidget.
+ the given \a device.
+
+ \obsolete
\sa begin(), {QPainter#Settings}{Settings}
*/
-void QPainter::initFrom(const QWidget *widget)
+void QPainter::initFrom(const QPaintDevice *device)
{
- Q_ASSERT_X(widget, "QPainter::initFrom(const QWidget *widget)", "Widget cannot be 0");
+ Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
Q_D(QPainter);
if (!d->engine) {
qWarning("QPainter::initFrom: Painter not active, aborted");
return;
}
- const QPalette &pal = widget->palette();
- d->state->pen = QPen(pal.brush(widget->foregroundRole()), 0);
- d->state->bgBrush = pal.brush(widget->backgroundRole());
- d->state->deviceFont = QFont(widget->font(), const_cast<QWidget*> (widget));
- d->state->font = d->state->deviceFont;
+ device->initPainter(this);
+
if (d->extended) {
d->extended->penChanged();
} else if (d->engine) {
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->helper_device = pd;
d->original_device = pd;
- QPaintDevice *rpd = 0;
QPoint redirectionOffset;
- // We know for sure that redirection is broken when the widget is inside
- // its paint event, so it's safe to use our hard-coded redirection. However,
- // there IS one particular case we still need to support, and that's
- // when people call QPainter::setRedirected in the widget's paint event right
- // before any painter is created (or QPainter::begin is called). In that
- // particular case our hard-coded redirection is restored and the redirection
- // is retrieved from QPainter::redirected (as before).
- if (pd->devType() == QInternal::Widget)
- rpd = static_cast<QWidget *>(pd)->d_func()->redirected(&redirectionOffset);
-
- if (!rpd)
- rpd = redirected(pd, &redirectionOffset);
-
+ QPaintDevice *rpd = pd->redirected(&redirectionOffset);
if (rpd)
pd = rpd;
d->engine->state = d->state;
switch (pd->devType()) {
- 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);
- if(!d->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
- && !paintOutsidePaintEvent && !inPaintEvent) {
- qWarning("QPainter::begin: Widget painting can only begin as a "
- "result of a paintEvent");
- qt_cleanup_painter_state(d);
- return false;
- }
-
- // 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;
- }
case QInternal::Pixmap:
{
QPixmap *pm = static_cast<QPixmap *>(pd);
// Copy painter properties from original paint device,
// required for QPixmap::grabWidget()
if (d->original_device->devType() == QInternal::Widget) {
- QWidget *widget = static_cast<QWidget *>(d->original_device);
- initFrom(widget);
+ initFrom(d->original_device);
} else {
d->state->layoutDirection = Qt::LayoutDirectionAuto;
// make sure we have a font compatible with the paintdevice
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}
*/
return;
}
+ if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
+ op = Qt::ReplaceClip;
+
d->state->clipRegion = rect;
d->state->clipOperation = op;
if (op == Qt::NoClip || op == Qt::ReplaceClip)
return;
}
+ if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
+ op = Qt::ReplaceClip;
+
d->state->clipRegion = r;
d->state->clipOperation = op;
if (op == Qt::NoClip || op == Qt::ReplaceClip)
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)
{
return;
}
+ if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
+ op = Qt::ReplaceClip;
+
d->state->clipPath = path;
d->state->clipOperation = op;
if (op == Qt::NoClip || op == Qt::ReplaceClip)
\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
- example},{demos/deform}{the Vector Deformation demo}
+ example},{painting/deform}{the Vector Deformation example}
*/
void QPainter::drawPath(const QPainterPath &path)
{
\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}
*/
/*!
- \fn void QPainter::drawPoints(const QPolygon &polygon, int index,
- int count)
-
- \overload
- \compat
-
- Draws \a count points in the vector \a polygon starting on \a index
- using the current pen.
-
- Use drawPoints() combined with QPolygon::constData() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawPoints(polygon, index, count);
- \newcode
- int pointCount = (count == -1) ? polygon.size() - index : count;
-
- QPainter painter(this);
- painter.drawPoints(polygon.constData() + index, pointCount);
- \endcode
-*/
-
-/*!
Sets the background mode of the painter to the given \a mode
Qt::TransparentMode (the default) draws stippled lines and text
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}
startAngle and \a spanAngle.
*/
-#ifdef QT3_SUPPORT
-/*!
- \fn void QPainter::drawLineSegments(const QPolygon &polygon, int
- index, int count)
-
- Draws \a count separate lines from points defined by the \a
- polygon, starting at \a{polygon}\e{[index]} (\a index defaults to
- 0). If \a count is -1 (the default) all points until the end of
- the array are used.
-
- Use drawLines() combined with QPolygon::constData() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawLineSegments(polygon, index, count);
- \newcode
- int lineCount = (count == -1) ? (polygon.size() - index) / 2 : count;
-
- QPainter painter(this);
- painter.drawLines(polygon.constData() + index * 2, lineCount);
- \endcode
-*/
-
-void QPainter::drawLineSegments(const QPolygon &a, int index, int nlines)
-{
-#ifdef QT_DEBUG_DRAW
- if (qt_show_painter_debug_output)
- printf("QPainter::drawLineSegments(), count=%d\n", a.size()/2);
-#endif
- Q_D(QPainter);
-
- if (!d->engine)
- return;
-
- if (nlines < 0)
- nlines = a.size()/2 - index/2;
- if (index + nlines*2 > (int)a.size())
- nlines = (a.size() - index)/2;
- if (nlines < 1 || index < 0)
- return;
-
- if (d->extended) {
- // FALCON: Use QVectorPath
- QVector<QLineF> lines;
- for (int i=index; i<index + nlines*2; i+=2)
- lines << QLineF(a.at(i), a.at(i+1));
- d->extended->drawLines(lines.data(), lines.size());
- return;
- }
-
- d->updateState(d->state);
-
- QVector<QLineF> lines;
- if (d->state->emulationSpecifier) {
- if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
- && d->state->matrix.type() == QTransform::TxTranslate) {
- QPointF offset(d->state->matrix.dx(), d->state->matrix.dy());
- for (int i=index; i<index + nlines*2; i+=2)
- lines << QLineF(a.at(i) + offset, a.at(i+1) + offset);
- } else {
- QPainterPath linesPath;
- for (int i=index; i<index + nlines*2; i+=2) {
- linesPath.moveTo(a.at(i));
- linesPath.lineTo(a.at(i+1));
- }
- d->draw_helper(linesPath, QPainterPrivate::StrokeDraw);
- return;
- }
- } else {
- for (int i=index; i<index + nlines*2; i+=2)
- lines << QLineF(a.at(i), a.at(i+1));
- }
-
- d->engine->drawLines(lines.data(), lines.size());
-}
-#endif // QT3_SUPPORT
/*!
Draws the first \a lineCount lines in the array \a lines
\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}
}
/*!
- \fn void QPainter::drawPolyline(const QPolygon &polygon, int index, int
- count)
-
- \overload
- \compat
-
- Draws the polyline defined by the \a count lines of the given \a
- polygon starting at \a index (\a index defaults to 0).
-
- Use drawPolyline() combined with QPolygon::constData() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawPolyline(polygon, index, count);
- \newcode
- int pointCount = (count == -1) ? polygon.size() - index : count;
-
- QPainter painter(this);
- painter.drawPolyline(polygon.constData() + index, pointCount);
- \endcode
-*/
-
-/*!
\fn void QPainter::drawPolyline(const QPolygonF &points)
\overload
\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)
{
d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
}
-/*! \fn void QPainter::drawPolygon(const QPolygonF &polygon, bool winding, int index = 0,
- int count = -1)
- \compat
- \overload
-
- Use drawPolygon() combined with QPolygonF::constData() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawPolygon(polygon, winding, index, count);
- \newcode
- int pointCount = (count == -1) ? polygon.size() - index : count;
- int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
-
- QPainter painter(this);
- painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
- \endcode
-*/
-
-/*! \fn void QPainter::drawPolygon(const QPolygon &polygon, bool winding,
- int index = 0, int count = -1)
-
- \compat
- \overload
-
- Use drawPolygon() combined with QPolygon::constData() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawPolygon(polygon, winding, index, count);
- \newcode
- int pointCount = (count == -1) ? polygon.size() - index : count;
- int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
-
- QPainter painter(this);
- painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
- \endcode
-*/
-
/*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
\overload
\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
pen and brush.
*/
-/*!
- \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon, int
- index, int count)
-
- \compat
- \overload
-
- Use drawConvexPolygon() combined with QPolygonF::constData()
- instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawConvexPolygon(polygon, index, count);
- \newcode
- int pointCount = (count == -1) ? polygon.size() - index : count;
-
- QPainter painter(this);
- painter.drawConvexPolygon(polygon.constData() + index, pointCount);
- \endcode
-*/
-
-/*!
- \fn void QPainter::drawConvexPolygon(const QPolygon &polygon, int
- index, int count)
-
- \compat
- \overload
-
- Use drawConvexPolygon() combined with QPolygon::constData()
- instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawConvexPolygon(polygon, index, count);
- \newcode
- int pointCount = (count == -1) ? polygon.size() - index : count;
-
- QPainter painter(this);
- painter.drawConvexPolygon(polygon.constData() + index, pointCount);
- \endcode
-*/
-
void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
{
#ifdef QT_DEBUG_DRAW
\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::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
qreal x = p.x();
qreal y = p.y();
+ bool rtl = ti.flags & QTextItem::RightToLeft;
+ if (rtl)
+ x += ti.width.toReal();
+
int start = 0;
int end, i;
for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
ti2.width += ti.glyphs.effectiveAdvance(i);
}
- d->engine->drawTextItem(QPointF(x, y), ti2);
+ if (rtl)
+ x -= ti2.width.toReal();
+
+ engine->drawTextItem(QPointF(x, y), ti2);
+
+ if (!rtl)
+ x += ti2.width.toReal();
// reset the high byte for all glyphs and advance to the next sub-string
const int hi = which << 24;
for (i = start; i < end; ++i) {
glyphs.glyphs[i] = hi | glyphs.glyphs[i];
}
- x += ti2.width.toReal();
// change engine
start = end;
ti2.width += ti.glyphs.effectiveAdvance(i);
}
- if (d->extended)
- d->extended->drawTextItem(QPointF(x, y), ti2);
+ if (rtl)
+ x -= ti2.width.toReal();
+
+ 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}
*/
return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
}
-/*! \fn bool QPainter::hasViewXForm() const
- \compat
-
- Use viewTransformEnabled() instead.
-*/
-
-/*! \fn bool QPainter::hasWorldXForm() const
- \compat
-
- Use worldMatrixEnabled() instead.
-*/
-
-/*! \fn void QPainter::resetXForm()
- \compat
-
- Use resetTransform() instead.
-*/
-
-/*! \fn void QPainter::setViewXForm(bool enabled)
- \compat
-
- Use setViewTransformEnabled() instead.
-*/
-
-/*! \fn void QPainter::setWorldXForm(bool enabled)
- \compat
-
- Use setWorldMatrixEnabled() instead.
-*/
/*!
Enables view transformations if \a enable is true, or disables
view transformations if \a enable is false.
d->updateMatrix();
}
-#ifdef QT3_SUPPORT
-
/*!
+ \threadsafe
+
\obsolete
- Use the worldTransform() combined with QTransform::dx() instead.
+ Please use QWidget::render() instead.
- \oldcode
- QPainter painter(this);
- qreal x = painter.translationX();
- \newcode
- QPainter painter(this);
- qreal x = painter.worldTransform().dx();
- \endcode
-*/
-qreal QPainter::translationX() const
-{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::translationX: Painter not active");
- return 0.0;
- }
- return d->state->worldMatrix.dx();
-}
+ Redirects all paint commands for the given paint \a device, to the
+ \a replacement device. The optional point \a offset defines an
+ offset within the source device.
-/*!
- \obsolete
+ The redirection will not be effective until the begin() function
+ has been called; make sure to call end() for the given \a
+ device's painter (if any) before redirecting. Call
+ restoreRedirected() to restore the previous redirection.
- Use the worldTransform() combined with QTransform::dy() instead.
+ \warning Making use of redirections in the QPainter API implies
+ that QPainter::begin() and QPaintDevice destructors need to hold
+ a mutex for a short period. This can impact performance. Use of
+ QWidget::render is strongly encouraged.
- \oldcode
- QPainter painter(this);
- qreal y = painter.translationY();
- \newcode
- QPainter painter(this);
- qreal y = painter.worldTransform().dy();
- \endcode
+ \sa redirected(), restoreRedirected()
*/
-qreal QPainter::translationY() const
+void QPainter::setRedirected(const QPaintDevice *device,
+ QPaintDevice *replacement,
+ const QPoint &offset)
{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::translationY: Painter not active");
- return 0.0;
- }
- return d->state->worldMatrix.dy();
+ 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");
}
/*!
- \fn void QPainter::map(int x, int y, int *rx, int *ry) const
+ \threadsafe
- \internal
+ \obsolete
- Sets (\a{rx}, \a{ry}) to the point that results from applying the
- painter's current transformation on the point (\a{x}, \a{y}).
-*/
-void QPainter::map(int x, int y, int *rx, int *ry) const
+ Using QWidget::render() obsoletes the use of this function.
+
+ Restores the previous redirection for the given \a device after a
+ call to setRedirected().
+
+ \warning Making use of redirections in the QPainter API implies
+ that QPainter::begin() and QPaintDevice destructors need to hold
+ a mutex for a short period. This can impact performance. Use of
+ QWidget::render is strongly encouraged.
+
+ \sa redirected()
+ */
+void QPainter::restoreRedirected(const QPaintDevice *device)
{
- QPoint p(x, y);
- p = p * combinedMatrix();
- *rx = p.x();
- *ry = p.y();
+ Q_UNUSED(device)
+ qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
}
/*!
- \fn QPoint QPainter::xForm(const QPoint &point) const
+ \threadsafe
- Use combinedTransform() instead.
-*/
+ \obsolete
-QPoint QPainter::xForm(const QPoint &p) const
-{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::xForm: Painter not active");
- return QPoint();
- }
- if (d->state->matrix.type() == QTransform::TxNone)
- return p;
- return p * combinedMatrix();
-}
+ Using QWidget::render() obsoletes the use of this function.
+ Returns the replacement for given \a device. The optional out
+ parameter \a offset returns the offset within the replaced device.
-/*!
- \fn QRect QPainter::xForm(const QRect &rectangle) const
- \overload
+ \warning Making use of redirections in the QPainter API implies
+ that QPainter::begin() and QPaintDevice destructors need to hold
+ a mutex for a short period. This can impact performance. Use of
+ QWidget::render is strongly encouraged.
- Use combinedTransform() instead of this function and call
- mapRect() on the result to obtain a QRect.
+ \sa setRedirected(), restoreRedirected()
*/
-
-QRect QPainter::xForm(const QRect &r) const
+QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::xForm: Painter not active");
- return QRect();
- }
- if (d->state->matrix.type() == QTransform::TxNone)
- return r;
- return combinedMatrix().mapRect(r);
-}
-
-/*!
- \fn QPolygon QPainter::xForm(const QPolygon &polygon) const
- \overload
-
- Use combinedTransform() instead.
-*/
-
-QPolygon QPainter::xForm(const QPolygon &a) const
-{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::xForm: Painter not active");
- return QPolygon();
- }
- if (d->state->matrix.type() == QTransform::TxNone)
- return a;
- return a * combinedMatrix();
-}
-
-/*!
- \fn QPolygon QPainter::xForm(const QPolygon &polygon, int index, int count) const
- \overload
-
- Use combinedTransform() combined with QPolygon::mid() instead.
-
- \oldcode
- QPainter painter(this);
- QPolygon transformed = painter.xForm(polygon, index, count)
- \newcode
- QPainter painter(this);
- QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform();
- \endcode
-*/
-
-QPolygon QPainter::xForm(const QPolygon &av, int index, int npoints) const
-{
- int lastPoint = npoints < 0 ? av.size() : index+npoints;
- QPolygon a(lastPoint-index);
- memcpy(a.data(), av.data()+index, (lastPoint-index)*sizeof(QPoint));
- return a * combinedMatrix();
-}
-
-/*!
- \fn QPoint QPainter::xFormDev(const QPoint &point) const
- \overload
- \obsolete
-
- Use combinedTransform() combined with QTransform::inverted() instead.
-
- \oldcode
- QPainter painter(this);
- QPoint transformed = painter.xFormDev(point);
- \newcode
- QPainter painter(this);
- QPoint transformed = point * painter.combinedTransform().inverted();
- \endcode
-*/
-
-QPoint QPainter::xFormDev(const QPoint &p) const
-{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::xFormDev: Painter not active");
- return QPoint();
- }
- if(d->state->matrix.type() == QTransform::TxNone)
- return p;
- return p * combinedMatrix().inverted();
-}
-
-/*!
- \fn QRect QPainter::xFormDev(const QRect &rectangle) const
- \overload
- \obsolete
-
- Use combinedTransform() combined with QTransform::inverted() instead.
-
- \oldcode
- QPainter painter(this);
- QRect transformed = painter.xFormDev(rectangle);
- \newcode
- QPainter painter(this);
- QRegion region = QRegion(rectangle) * painter.combinedTransform().inverted();
- QRect transformed = region.boundingRect();
- \endcode
-*/
-
-QRect QPainter::xFormDev(const QRect &r) const
-{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::xFormDev: Painter not active");
- return QRect();
- }
- if (d->state->matrix.type() == QTransform::TxNone)
- return r;
- return combinedMatrix().inverted().mapRect(r);
-}
-
-/*!
- \overload
-
- \fn QPoint QPainter::xFormDev(const QPolygon &polygon) const
- \obsolete
-
- Use combinedTransform() combined with QTransform::inverted() instead.
-
- \oldcode
- QPainter painter(this);
- QPolygon transformed = painter.xFormDev(rectangle);
- \newcode
- QPainter painter(this);
- QPolygon transformed = polygon * painter.combinedTransform().inverted();
- \endcode
-*/
-
-QPolygon QPainter::xFormDev(const QPolygon &a) const
-{
- Q_D(const QPainter);
- if (!d->engine) {
- qWarning("QPainter::xFormDev: Painter not active");
- return QPolygon();
- }
- if (d->state->matrix.type() == QTransform::TxNone)
- return a;
- return a * combinedMatrix().inverted();
-}
-
-/*!
- \fn QPolygon QPainter::xFormDev(const QPolygon &polygon, int index, int count) const
- \overload
- \obsolete
-
- Use combinedTransform() combined with QPolygon::mid() and QTransform::inverted() instead.
-
- \oldcode
- QPainter painter(this);
- QPolygon transformed = painter.xFormDev(polygon, index, count);
- \newcode
- QPainter painter(this);
- QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform().inverted();
- \endcode
-*/
-
-QPolygon QPainter::xFormDev(const QPolygon &ad, int index, int npoints) const
-{
- Q_D(const QPainter);
- int lastPoint = npoints < 0 ? ad.size() : index+npoints;
- QPolygon a(lastPoint-index);
- memcpy(a.data(), ad.data()+index, (lastPoint-index)*sizeof(QPoint));
- if (d->state->matrix.type() == QTransform::TxNone)
- return a;
- return a * combinedMatrix().inverted();
-}
-
-/*!
- \fn void QPainter::drawCubicBezier(const QPolygon &controlPoints, int index)
-
- Draws a cubic Bezier curve defined by the \a controlPoints,
- starting at \a{controlPoints}\e{[index]} (\a index defaults to 0).
- Points after \a{controlPoints}\e{[index + 3]} are ignored. Nothing
- happens if there aren't enough control points.
-
- Use strokePath() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawCubicBezier(controlPoints, index)
- \newcode
- QPainterPath path;
- path.moveTo(controlPoints.at(index));
- path.cubicTo(controlPoints.at(index+1),
- controlPoints.at(index+2),
- controlPoints.at(index+3));
-
- QPainter painter(this);
- painter.strokePath(path, painter.pen());
- \endcode
-*/
-void QPainter::drawCubicBezier(const QPolygon &a, int index)
-{
- Q_D(QPainter);
-
- if (!d->engine)
- return;
-
- if ((int)a.size() - index < 4) {
- qWarning("QPainter::drawCubicBezier: Cubic Bezier needs 4 control "
- "points");
- return;
- }
-
- QPainterPath path;
- path.moveTo(a.at(index));
- path.cubicTo(a.at(index+1), a.at(index+2), a.at(index+3));
- strokePath(path, d->state->pen);
-}
-#endif
-
-struct QPaintDeviceRedirection
-{
- QPaintDeviceRedirection() : device(0), replacement(0), internalWidgetRedirectionIndex(-1) {}
- QPaintDeviceRedirection(const QPaintDevice *device, QPaintDevice *replacement,
- const QPoint& offset, int internalWidgetRedirectionIndex)
- : device(device), replacement(replacement), offset(offset),
- internalWidgetRedirectionIndex(internalWidgetRedirectionIndex) { }
- const QPaintDevice *device;
- QPaintDevice *replacement;
- QPoint offset;
- int internalWidgetRedirectionIndex;
- bool operator==(const QPaintDevice *pdev) const { return device == pdev; }
- Q_DUMMY_COMPARISON_OPERATOR(QPaintDeviceRedirection)
-};
-
-typedef QList<QPaintDeviceRedirection> QPaintDeviceRedirectionList;
-Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections)
-Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex)
-Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic)
-
-/*!
- \threadsafe
-
- \obsolete
-
- Please use QWidget::render() instead.
-
- Redirects all paint commands for the given paint \a device, to the
- \a replacement device. The optional point \a offset defines an
- offset within the source device.
-
- The redirection will not be effective until the begin() function
- has been called; make sure to call end() for the given \a
- device's painter (if any) before redirecting. Call
- restoreRedirected() to restore the previous redirection.
-
- \warning Making use of redirections in the QPainter API implies
- that QPainter::begin() and QPaintDevice destructors need to hold
- a mutex for a short period. This can impact performance. Use of
- QWidget::render is strongly encouraged.
-
- \sa redirected(), restoreRedirected()
-*/
-void QPainter::setRedirected(const QPaintDevice *device,
- QPaintDevice *replacement,
- const QPoint &offset)
-{
- Q_ASSERT(device != 0);
-
- bool hadInternalWidgetRedirection = false;
- if (device->devType() == QInternal::Widget) {
- const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
- // This is the case when the widget is in a paint event.
- if (widgetPrivate->redirectDev) {
- // Remove internal redirection and put it back into the global redirection list.
- QPoint oldOffset;
- QPaintDevice *oldReplacement = widgetPrivate->redirected(&oldOffset);
- const_cast<QWidgetPrivate *>(widgetPrivate)->restoreRedirected();
- setRedirected(device, oldReplacement, oldOffset);
- hadInternalWidgetRedirection = true;
- }
- }
-
- QPoint roffset;
- QPaintDevice *rdev = redirected(replacement, &roffset);
-
- QMutexLocker locker(globalRedirectionsMutex());
- QPaintDeviceRedirectionList *redirections = globalRedirections();
- Q_ASSERT(redirections != 0);
- *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset,
- hadInternalWidgetRedirection ? redirections->size() - 1 : -1);
- globalRedirectionAtomic()->ref();
-}
-
-/*!
- \threadsafe
-
- \obsolete
-
- Using QWidget::render() obsoletes the use of this function.
-
- Restores the previous redirection for the given \a device after a
- call to setRedirected().
-
- \warning Making use of redirections in the QPainter API implies
- that QPainter::begin() and QPaintDevice destructors need to hold
- a mutex for a short period. This can impact performance. Use of
- QWidget::render is strongly encouraged.
-
- \sa redirected()
- */
-void QPainter::restoreRedirected(const QPaintDevice *device)
-{
- Q_ASSERT(device != 0);
- QMutexLocker locker(globalRedirectionsMutex());
- QPaintDeviceRedirectionList *redirections = globalRedirections();
- Q_ASSERT(redirections != 0);
- for (int i = redirections->size()-1; i >= 0; --i) {
- if (redirections->at(i) == device) {
- globalRedirectionAtomic()->deref();
- const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex;
- redirections->removeAt(i);
- // Restore the internal widget redirection, i.e. remove it from the global
- // redirection list and put it back into QWidgetPrivate. The index is only set when
- // someone call QPainter::setRedirected in a widget's paint event and we internally
- // have a redirection set (typically set in QWidgetPrivate::drawWidget).
- if (internalWidgetRedirectionIndex >= 0) {
- Q_ASSERT(internalWidgetRedirectionIndex < redirections->size());
- const QPaintDeviceRedirection &redirectionDevice = redirections->at(internalWidgetRedirectionIndex);
- QWidget *widget = static_cast<QWidget *>(const_cast<QPaintDevice *>(device));
- widget->d_func()->setRedirected(redirectionDevice.replacement, redirectionDevice.offset);
- redirections->removeAt(internalWidgetRedirectionIndex);
- }
- return;
- }
- }
-}
-
-/*!
- \threadsafe
-
- \obsolete
-
- Using QWidget::render() obsoletes the use of this function.
-
- Returns the replacement for given \a device. The optional out
- parameter \a offset returns the offset within the replaced device.
-
- \warning Making use of redirections in the QPainter API implies
- that QPainter::begin() and QPaintDevice destructors need to hold
- a mutex for a short period. This can impact performance. Use of
- QWidget::render is strongly encouraged.
-
- \sa setRedirected(), restoreRedirected()
-*/
-QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
-{
- Q_ASSERT(device != 0);
-
- if (device->devType() == QInternal::Widget) {
- const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
- if (widgetPrivate->redirectDev)
- return widgetPrivate->redirected(offset);
- }
-
- if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
- return 0;
-
- QMutexLocker locker(globalRedirectionsMutex());
- QPaintDeviceRedirectionList *redirections = globalRedirections();
- Q_ASSERT(redirections != 0);
- for (int i = redirections->size()-1; i >= 0; --i)
- if (redirections->at(i) == device) {
- if (offset)
- *offset = redirections->at(i).offset;
- return redirections->at(i).replacement;
- }
- if (offset)
- *offset = QPoint(0, 0);
- return 0;
-}
-
-
-void qt_painter_removePaintDevice(QPaintDevice *dev)
-{
- if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
- return;
-
- QMutex *mutex = 0;
- QT_TRY {
- mutex = globalRedirectionsMutex();
- } QT_CATCH(...) {
- // ignore the missing mutex, since we could be called from
- // a destructor, and destructors shall not throw
- }
- QMutexLocker locker(mutex);
- QPaintDeviceRedirectionList *redirections = 0;
- QT_TRY {
- redirections = globalRedirections();
- } QT_CATCH(...) {
- // do nothing - code below is safe with redirections being 0.
- }
- if (redirections) {
- for (int i = 0; i < redirections->size(); ) {
- if(redirections->at(i) == dev || redirections->at(i).replacement == dev)
- redirections->removeAt(i);
- else
- ++i;
- }
- }
+ Q_UNUSED(device)
+ Q_UNUSED(offset)
+ return 0;
}
void qt_format_text(const QFont &fnt, const QRectF &_r,
else
layout_direction = Qt::LeftToRight;
- tf = QStyle::visualAlignment(layout_direction, QFlag(tf));
+ tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
bool isRightToLeft = layout_direction == Qt::RightToLeft;
bool expandtabs = ((tf & Qt::TextExpandTabs) &&
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) {
wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
opacity(1), WxF(false), VxF(false), clipEnabled(true),
bgMode(Qt::TransparentMode), painter(0),
- layoutDirection(QApplication::layoutDirection()),
+ layoutDirection(QGuiApplication::layoutDirection()),
composition_mode(QPainter::CompositionMode_SourceOver),
emulationSpecifier(0), changeFlags(0)
{
clipInfo.clear();
worldMatrix.reset();
matrix.reset();
- layoutDirection = QApplication::layoutDirection();
+ layoutDirection = QGuiApplication::layoutDirection();
composition_mode = QPainter::CompositionMode_SourceOver;
emulationSpecifier = 0;
dirtyFlags = 0;
opacity = 1;
}
-#ifdef QT3_SUPPORT
-static void bitBlt_helper(QPaintDevice *dst, const QPoint &dp,
- const QPaintDevice *src, const QRect &sr, bool)
-{
- Q_ASSERT(dst);
- Q_ASSERT(src);
-
- if (src->devType() == QInternal::Pixmap) {
- const QPixmap *pixmap = static_cast<const QPixmap *>(src);
- QPainter pt(dst);
- pt.drawPixmap(dp, *pixmap, sr);
-
- } else {
- qWarning("QPainter: bitBlt only works when source is of type pixmap");
- }
-}
-
-void bitBlt(QPaintDevice *dst, int dx, int dy,
- const QPaintDevice *src, int sx, int sy, int sw, int sh,
- bool ignoreMask )
-{
- bitBlt_helper(dst, QPoint(dx, dy), src, QRect(sx, sy, sw, sh), ignoreMask);
-}
-
-void bitBlt(QPaintDevice *dst, const QPoint &dp, const QPaintDevice *src, const QRect &sr, bool ignoreMask)
-{
- bitBlt_helper(dst, dp, src, sr, ignoreMask);
-}
-
-void bitBlt(QPaintDevice *dst, int dx, int dy,
- const QImage *src, int sx, int sy, int sw, int sh, int fl)
-{
- Qt::ImageConversionFlags flags(fl);
- QPixmap srcPixmap = QPixmap::fromImage(*src, flags);
- bitBlt_helper(dst, QPoint(dx, dy), &srcPixmap, QRect(sx, sy, sw, sh), false);
-}
-
-#endif // QT3_SUPPORT
-
-/*!
- \fn void QPainter::setBackgroundColor(const QColor &color)
-
- Use setBackground() instead.
-*/
-
-/*!
- \fn const QColor &QPainter::backgroundColor() const
-
- Use background() and QBrush::color() instead.
-
- \oldcode
- QColor myColor = backgroundColor();
- \newcode
- QColor myColor = background().color();
- \endcode
-
- Note that the background can be a complex brush such as a texture
- or a gradient.
-*/
-
-/*!
- \fn void QPainter::drawText(int x, int y, const QString &text, int pos, int length)
- \compat
-
- Use drawText() combined with QString::mid() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawText(x, y, text, pos, length);
- \newcode
- QPainter painter(this);
- painter.drawText(x, y, text.mid(pos, length));
- \endcode
-*/
-
-/*!
- \fn void QPainter::drawText(const QPoint &point, const QString &text, int pos, int length)
- \compat
-
- Use drawText() combined with QString::mid() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawText(point, text, pos, length);
- \newcode
- QPainter painter(this);
- painter.drawText(point, text.mid(pos, length));
- \endcode
-*/
-
-/*!
- \fn void QPainter::drawText(int x, int y, const QString &text, int length)
- \compat
-
- Use drawText() combined with QString::left() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawText(x, y, text, length);
- \newcode
- QPainter painter(this);
- painter.drawText(x, y, text.left(length));
- \endcode
-*/
-
-/*!
- \fn void QPainter::drawText(const QPoint &point, const QString &text, int length)
- \compat
-
- Use drawText() combined with QString::left() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawText(point, text, length);
- \newcode
- QPainter painter(this);
- painter.drawText(point, text.left(length));
- \endcode
-*/
-
-/*!
- \fn bool QPainter::begin(QPaintDevice *device, const QWidget *init)
- \compat
-
- Use begin() instead.
-
- If the paint \a device is a QWidget, QPainter is initialized after
- the widget's settings automatically. Otherwise, you must call the
- initFrom() function to initialize the painters pen, background and
- font to the same as any given widget.
-
- \oldcode
- QPainter painter(this);
- painter.begin(device, init);
- \newcode
- QPainter painter(this);
- painter.begin(device);
- painter.initFrom(init);
- \endcode
-*/
-
/*!
\fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
Qt::ImageConversionFlags flags)
\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()
*/
/*!
- \fn void QPainter::redirect(QPaintDevice *pdev, QPaintDevice *replacement)
-
- Use setRedirected() instead.
-*/
-
-/*!
- \fn QPaintDevice *QPainter::redirect(QPaintDevice *pdev)
-
- Use redirected() instead.
-*/
-
-/*!
- \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
- const QString &text, int length)
- \compat
-
- Returns the bounding rectangle for the given \a length of the \a
- text constrained by the provided \a rectangle.
-
- Use boundingRect() combined with QString::left() instead.
-
- \oldcode
- QRect rectangle = boundingRect(rect, flags, text, length);
- \newcode
- QRect rectangle = boundingRect(rect, flags, text.left(length));
- \endcode
-*/
-
-/*!
- \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text,
- int length, QRect *br)
- \compat
-
- Use drawText() combined with QString::left() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawText(rectangle, flags, text, length, br );
- \newcode
- QPainter painter(this);
- painter.drawText(rectangle, flags, text.left(length), br );
- \endcode
-*/
-
-/*!
- \fn QRect QPainter::boundingRect(int x, int y, int width, int height, int flags,
- const QString &text, int length);
-
- \compat
-
- Returns the bounding rectangle for the given \a length of the \a
- text constrained by the rectangle that begins at point (\a{x},
- \a{y}) with the given \a width and \a height.
-
- Use boundingRect() combined with QString::left() instead.
-
- \oldcode
- QRect rectangle = boundingRect(x, y, width, height, flags, text, length);
- \newcode
- QRect rectangle = boundingRect(x, y, width, height, flags, text.left(length));
- \endcode
-*/
-
-/*!
- \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
- const QString &text, int length, QRect *br)
-
- \compat
-
- Use drawText() combined with QString::left() instead.
-
- \oldcode
- QPainter painter(this);
- painter.drawText(x, y, width, height, flags, text, length, br );
- \newcode
- QPainter painter(this);
- painter.drawText(x, y, width, height, flags, text.left(length), br );
- \endcode
-*/
-
-
-/*!
\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
p->draw_helper(path, operation);
}
-/*! \fn Display *QPaintDevice::x11Display() const
- Use QX11Info::display() instead.
-
- \oldcode
- Display *display = widget->x11Display();
- \newcode
- Display *display = QX11Info::display();
- \endcode
-
- \sa QWidget::x11Info(), QX11Info::display()
-*/
-
-/*! \fn int QPaintDevice::x11Screen() const
- Use QX11Info::screen() instead.
-
- \oldcode
- int screen = widget->x11Screen();
- \newcode
- int screen = widget->x11Info().screen();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn void *QPaintDevice::x11Visual() const
- Use QX11Info::visual() instead.
-
- \oldcode
- void *visual = widget->x11Visual();
- \newcode
- void *visual = widget->x11Info().visual();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn int QPaintDevice::x11Depth() const
- Use QX11Info::depth() instead.
-
- \oldcode
- int depth = widget->x11Depth();
- \newcode
- int depth = widget->x11Info().depth();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn int QPaintDevice::x11Cells() const
- Use QX11Info::cells() instead.
-
- \oldcode
- int cells = widget->x11Cells();
- \newcode
- int cells = widget->x11Info().cells();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn Qt::HANDLE QPaintDevice::x11Colormap() const
- Use QX11Info::colormap() instead.
-
- \oldcode
- unsigned long screen = widget->x11Colormap();
- \newcode
- unsigned long screen = widget->x11Info().colormap();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn bool QPaintDevice::x11DefaultColormap() const
- Use QX11Info::defaultColormap() instead.
-
- \oldcode
- bool isDefault = widget->x11DefaultColormap();
- \newcode
- bool isDefault = widget->x11Info().defaultColormap();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn bool QPaintDevice::x11DefaultVisual() const
- Use QX11Info::defaultVisual() instead.
-
- \oldcode
- bool isDefault = widget->x11DefaultVisual();
- \newcode
- bool isDefault = widget->x11Info().defaultVisual();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn void *QPaintDevice::x11AppVisual(int screen)
- Use QX11Info::visual() instead.
-
- \oldcode
- void *visual = QPaintDevice::x11AppVisual(screen);
- \newcode
- void *visual = qApp->x11Info(screen).visual();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn Qt::HANDLE QPaintDevice::x11AppColormap(int screen)
- Use QX11Info::colormap() instead.
-
- \oldcode
- unsigned long colormap = QPaintDevice::x11AppColormap(screen);
- \newcode
- unsigned long colormap = qApp->x11Info(screen).colormap();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn Display *QPaintDevice::x11AppDisplay()
- Use QX11Info::display() instead.
-
- \oldcode
- Display *display = QPaintDevice::x11AppDisplay();
- \newcode
- Display *display = qApp->x11Info().display();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn int QPaintDevice::x11AppScreen()
- Use QX11Info::screen() instead.
-
- \oldcode
- int screen = QPaintDevice::x11AppScreen();
- \newcode
- int screen = qApp->x11Info().screen();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn int QPaintDevice::x11AppDepth(int screen)
- Use QX11Info::depth() instead.
-
- \oldcode
- int depth = QPaintDevice::x11AppDepth(screen);
- \newcode
- int depth = qApp->x11Info(screen).depth();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn int QPaintDevice::x11AppCells(int screen)
- Use QX11Info::cells() instead.
-
- \oldcode
- int cells = QPaintDevice::x11AppCells(screen);
- \newcode
- int cells = qApp->x11Info(screen).cells();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn Qt::HANDLE QPaintDevice::x11AppRootWindow(int screen)
- Use QX11Info::appRootWindow() instead.
-
- \oldcode
- unsigned long window = QPaintDevice::x11AppRootWindow(screen);
- \newcode
- unsigned long window = qApp->x11Info(screen).appRootWindow();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn bool QPaintDevice::x11AppDefaultColormap(int screen)
- Use QX11Info::defaultColormap() instead.
-
- \oldcode
- bool isDefault = QPaintDevice::x11AppDefaultColormap(screen);
- \newcode
- bool isDefault = qApp->x11Info(screen).defaultColormap();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn bool QPaintDevice::x11AppDefaultVisual(int screen)
- Use QX11Info::defaultVisual() instead.
-
- \oldcode
- bool isDefault = QPaintDevice::x11AppDefaultVisual(screen);
- \newcode
- bool isDefault = qApp->x11Info(screen).defaultVisual();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn void QPaintDevice::x11SetAppDpiX(int dpi, int screen)
- Use QX11Info::setAppDpiX() instead.
-*/
-
-/*! \fn void QPaintDevice::x11SetAppDpiY(int dpi, int screen)
- Use QX11Info::setAppDpiY() instead.
-*/
-
-/*! \fn int QPaintDevice::x11AppDpiX(int screen)
- Use QX11Info::appDpiX() instead.
-
- \oldcode
- bool isDefault = QPaintDevice::x11AppDpiX(screen);
- \newcode
- bool isDefault = qApp->x11Info(screen).appDpiX();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn int QPaintDevice::x11AppDpiY(int screen)
- Use QX11Info::appDpiY() instead.
-
- \oldcode
- bool isDefault = QPaintDevice::x11AppDpiY(screen);
- \newcode
- bool isDefault = qApp->x11Info(screen).appDpiY();
- \endcode
-
- \sa QWidget::x11Info(), QPixmap::x11Info()
-*/
-
-/*! \fn HDC QPaintDevice::getDC() const
- \internal
-*/
-
-/*! \fn void QPaintDevice::releaseDC(HDC) const
- \internal
-*/
-
-/*! \fn QWSDisplay *QPaintDevice::qwsDisplay()
- \internal
-*/
-
QT_END_NAMESPACE