/****************************************************************************
**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** 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>
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
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);
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}
*/
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)
{
\row
\li \inlineimage qpainter-path.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
+ \snippet code/src_gui_painting_qpainter.cpp 5
\endtable
\sa {painting/painterpaths}{the Painter Paths
\row
\li \inlineimage qpainter-line.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
+ \snippet code/src_gui_painting_qpainter.cpp 6
\endtable
\sa drawLines(), drawPolyline(), {Coordinate System}
\row
\li \inlineimage qpainter-rectangle.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
+ \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();
\row
\li \inlineimage qpainter-roundrect.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
+ \snippet code/src_gui_painting_qpainter.cpp 8
\endtable
\sa drawRect(), QPen
\row
\li \inlineimage qpainter-ellipse.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
+ \snippet code/src_gui_painting_qpainter.cpp 9
\endtable
\sa drawPie(), {Coordinate System}
\row
\li \inlineimage qpainter-arc.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
+ \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().
\row
\li \inlineimage qpainter-pie.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
+ \snippet code/src_gui_painting_qpainter.cpp 11
\endtable
\sa drawEllipse(), drawChord(), {Coordinate System}
\row
\li \inlineimage qpainter-chord.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
+ \snippet code/src_gui_painting_qpainter.cpp 12
\endtable
\sa drawArc(), drawPie(), {Coordinate System}
\table 100%
\row
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
+ \snippet code/src_gui_painting_qpainter.cpp 13
\endtable
\sa drawLines(), drawPolygon(), {Coordinate System}
\row
\li \inlineimage qpainter-polygon.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
+ \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)
{
\row
\li \inlineimage qpainter-polygon.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
+ \snippet code/src_gui_painting_qpainter.cpp 15
\endtable
The first point is implicitly connected to the last point, and the
\table 100%
\row
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
+ \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<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));
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.d->engineForScript(QUnicodeTables::Common),
+ 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
\li \inlineimage qpainter-text.png
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
+ \snippet code/src_gui_painting_qpainter.cpp 17
\endtable
The \a boundingRect (if not null) is set to the what the bounding rectangle
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()
*/
/*!
\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);
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) {
\table 100%
\row
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
+ \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");
\table 100%
\row
\li
- \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
+ \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.
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