summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/qoutlinemapper.cpp21
-rw-r--r--src/gui/painting/qpaintengine.cpp3
-rw-r--r--src/gui/painting/qpainter.cpp21
-rw-r--r--src/gui/painting/qpainter.h1
-rw-r--r--src/gui/painting/qpdf.cpp8
-rw-r--r--src/gui/painting/qregion.cpp10
-rw-r--r--src/gui/painting/qrgba64.h38
7 files changed, 67 insertions, 35 deletions
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index 7245b44fc7..f1e4ce5820 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -78,10 +78,23 @@ void QOutlineMapper::curveTo(const QPointF &cp1, const QPointF &cp2, const QPoin
#endif
QBezier bezier = QBezier::fromPoints(m_elements.last(), cp1, cp2, ep);
- bezier.addToPolygon(m_elements, m_curve_threshold);
- m_element_types.reserve(m_elements.size());
- for (int i = m_elements.size() - m_element_types.size(); i; --i)
- m_element_types << QPainterPath::LineToElement;
+
+ bool outsideClip = false;
+ // Test one point first before doing a full intersection test.
+ if (!QRectF(m_clip_rect).contains(m_transform.map(ep))) {
+ QRectF potentialCurveArea = m_transform.mapRect(bezier.bounds());
+ outsideClip = !potentialCurveArea.intersects(m_clip_rect);
+ }
+ if (outsideClip) {
+ // The curve is entirely outside the clip rect, so just
+ // approximate it with a line that closes the path.
+ lineTo(ep);
+ } else {
+ bezier.addToPolygon(m_elements, m_curve_threshold);
+ m_element_types.reserve(m_elements.size());
+ for (int i = m_elements.size() - m_element_types.size(); i; --i)
+ m_element_types << QPainterPath::LineToElement;
+ }
Q_ASSERT(m_elements.size() == m_element_types.size());
}
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index d59d843f8a..020392409d 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -310,6 +310,7 @@ struct QT_Point {
int x;
int y;
};
+Q_DECLARE_TYPEINFO(QT_Point, Q_PRIMITIVE_TYPE);
/*!
\fn void QPaintEngine::drawPolygon(const QPointF *points, int pointCount,
@@ -340,6 +341,8 @@ struct QT_PointF {
qreal x;
qreal y;
};
+Q_DECLARE_TYPEINFO(QT_PointF, Q_PRIMITIVE_TYPE);
+
/*!
\overload
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index e70079915a..aeb76589e0 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -6183,7 +6183,8 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
QString key = QLatin1String("WaveUnderline-")
% pen.color().name()
- % HexString<qreal>(radiusBase);
+ % HexString<qreal>(radiusBase)
+ % HexString<qreal>(pen.widthF());
QPixmap pixmap;
if (QPixmapCache::find(key, pixmap))
@@ -6191,7 +6192,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
- const int radius = qFloor(radiusBase);
+ const qreal radius = qFloor(radiusBase * 2) / 2.;
QPainterPath path;
@@ -6214,7 +6215,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
// due to it having a rather thick width for the regular underline.
const qreal maxPenWidth = .8 * radius;
if (wavePen.widthF() > maxPenWidth)
- wavePen.setWidth(maxPenWidth);
+ wavePen.setWidthF(maxPenWidth);
QPainter imgPainter(&pixmap);
imgPainter.setPen(wavePen);
@@ -6254,9 +6255,6 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
painter->setRenderHint(QPainter::Qt4CompatiblePainting, false);
const qreal underlineOffset = fe->underlinePosition().toReal();
- // deliberately ceil the offset to avoid the underline coming too close to
- // the text above it.
- const qreal underlinePos = pos.y() + qCeil(underlineOffset) + 0.5;
if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
@@ -6267,19 +6265,26 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
if (underlineStyle == QTextCharFormat::WaveUnderline) {
painter->save();
painter->translate(0, pos.y() + 1);
+ qreal maxHeight = fe->descent().toReal() - qreal(1);
QColor uc = charFormat.underlineColor();
if (uc.isValid())
pen.setColor(uc);
// Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
- const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
- const int descent = (int) fe->descent().toReal();
+ const QPixmap wave = generateWavyPixmap(qMin(qMax(underlineOffset, pen.widthF()), maxHeight / 2.), pen);
+ const int descent = qFloor(maxHeight);
painter->setBrushOrigin(painter->brushOrigin().x(), 0);
painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
painter->restore();
} else if (underlineStyle != QTextCharFormat::NoUnderline) {
+ // Deliberately ceil the offset to avoid the underline coming too close to
+ // the text above it, but limit it to stay within descent.
+ qreal adjustedUnderlineOffset = std::ceil(underlineOffset) + 0.5;
+ if (underlineOffset <= fe->descent().toReal())
+ adjustedUnderlineOffset = qMin(adjustedUnderlineOffset, fe->descent().toReal() - 0.5);
+ const qreal underlinePos = pos.y() + adjustedUnderlineOffset;
QColor uc = charFormat.underlineColor();
if (uc.isValid())
pen.setColor(uc);
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index bd745e41ba..5743d97405 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -486,6 +486,7 @@ private:
friend class QPreviewPaintEngine;
friend class QTextEngine;
};
+Q_DECLARE_TYPEINFO(QPainter::PixmapFragment, Q_RELOCATABLE_TYPE);
Q_DECLARE_OPERATORS_FOR_FLAGS(QPainter::RenderHints)
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 02f9be197f..b014305796 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1201,7 +1201,7 @@ void QPdfEngine::setPen()
switch(d->pen.joinStyle()) {
case Qt::MiterJoin:
case Qt::SvgMiterJoin:
- *d->currentPage << d->pen.miterLimit() << "M ";
+ *d->currentPage << qMax(qreal(1.0), d->pen.miterLimit()) << "M ";
pdfJoinStyle = 0;
break;
case Qt::BevelJoin:
@@ -2214,8 +2214,10 @@ int QPdfEnginePrivate::generateGradientShader(const QGradient *gradient, const Q
case QGradient::RadialGradient:
return generateRadialGradientShader(static_cast<const QRadialGradient *>(gradient), matrix, alpha);
case QGradient::ConicalGradient:
- default:
- qWarning("Implement me!");
+ Q_UNIMPLEMENTED(); // ### Implement me!
+ break;
+ case QGradient::NoGradient:
+ break;
}
return 0;
}
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index abdfc7c8c7..b39a23e7f2 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -1139,7 +1139,15 @@ void addSegmentsToPath(Segment *segment, QPainterPath &path)
}
}
-}
+} // unnamed namespace
+
+// the following is really a lie, because Segments cannot be relocated, as they
+// reference each other by address. For the same reason, they aren't even copyable,
+// but the code works with the compiler-generated (wrong) copy and move special
+// members, so use this as an optimization. The only container these are used in
+// (a QVarLengthArray in qt_regionToPath()) is resized once up-front, so doesn't
+// have a problem with this, but benefits from not having to run Segment ctors:
+Q_DECLARE_TYPEINFO(Segment, Q_PRIMITIVE_TYPE);
Q_GUI_EXPORT QPainterPath qt_regionToPath(const QRegion &region)
{
diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h
index a87d3fbb35..27e1e6e06d 100644
--- a/src/gui/painting/qrgba64.h
+++ b/src/gui/painting/qrgba64.h
@@ -103,7 +103,7 @@ public:
Q_DECL_RELAXED_CONSTEXPR static
QRgba64 fromArgb32(uint rgb)
{
- return fromRgba(rgb >> 16, rgb >> 8, rgb, rgb >> 24);
+ return fromRgba(quint8(rgb >> 16), quint8(rgb >> 8), quint8(rgb), quint8(rgb >> 24));
}
Q_DECL_CONSTEXPR bool isOpaque() const
@@ -115,10 +115,10 @@ public:
return (rgba & alphaMask()) == 0;
}
- Q_DECL_CONSTEXPR quint16 red() const { return rgba >> RedShift; }
- Q_DECL_CONSTEXPR quint16 green() const { return rgba >> GreenShift; }
- Q_DECL_CONSTEXPR quint16 blue() const { return rgba >> BlueShift; }
- Q_DECL_CONSTEXPR quint16 alpha() const { return rgba >> AlphaShift; }
+ Q_DECL_CONSTEXPR quint16 red() const { return quint16(rgba >> RedShift); }
+ Q_DECL_CONSTEXPR quint16 green() const { return quint16(rgba >> GreenShift); }
+ Q_DECL_CONSTEXPR quint16 blue() const { return quint16(rgba >> BlueShift); }
+ Q_DECL_CONSTEXPR quint16 alpha() const { return quint16(rgba >> AlphaShift); }
void setRed(quint16 _red) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << RedShift)) | (quint64(_red) << RedShift); }
void setGreen(quint16 _green) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << GreenShift)) | (quint64(_green) << GreenShift); }
void setBlue(quint16 _blue) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << BlueShift)) | (quint64(_blue) << BlueShift); }
@@ -130,11 +130,11 @@ public:
Q_DECL_CONSTEXPR quint8 alpha8() const { return div_257(alpha()); }
Q_DECL_CONSTEXPR uint toArgb32() const
{
- return (alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8();
+ return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
}
Q_DECL_CONSTEXPR ushort toRgb16() const
{
- return (red() & 0xf800) | ((green() >> 10) << 5) | (blue() >> 11);
+ return ushort((red() & 0xf800) | ((green() >> 10) << 5) | (blue() >> 11));
}
Q_DECL_RELAXED_CONSTEXPR QRgba64 premultiplied() const
@@ -143,7 +143,7 @@ public:
const quint16 r = div_65535(red() * a);
const quint16 g = div_65535(green() * a);
const quint16 b = div_65535(blue() * a);
- return fromRgba64(r, g, b, a);
+ return fromRgba64(r, g, b, quint16(a));
}
Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied() const
@@ -169,18 +169,18 @@ public:
private:
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE quint64 alphaMask() { return Q_UINT64_C(0xffff) << AlphaShift; }
- static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint div_257_floor(uint x) { return (x - (x >> 8)) >> 8; }
- static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint div_257(uint x) { return div_257_floor(x + 128); }
- static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; }
+ static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE quint8 div_257_floor(uint x) { return quint8((x - (x >> 8)) >> 8); }
+ static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE quint8 div_257(quint16 x) { return div_257_floor(x + 128U); }
+ static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE quint16 div_65535(uint x) { return quint16((x + (x>>16) + 0x8000U) >> 16); }
Q_DECL_RELAXED_CONSTEXPR Q_ALWAYS_INLINE QRgba64 unpremultiplied_32bit() const
{
if (isOpaque() || isTransparent())
return *this;
const quint32 a = alpha();
- const quint16 r = (quint32(red()) * 0xffff + a/2) / a;
- const quint16 g = (quint32(green()) * 0xffff + a/2) / a;
- const quint16 b = (quint32(blue()) * 0xffff + a/2) / a;
- return fromRgba64(r, g, b, a);
+ const quint16 r = quint16((red() * 0xffff + a/2) / a);
+ const quint16 g = quint16((green() * 0xffff + a/2) / a);
+ const quint16 b = quint16((blue() * 0xffff + a/2) / a);
+ return fromRgba64(r, g, b, quint16(a));
}
Q_DECL_RELAXED_CONSTEXPR Q_ALWAYS_INLINE QRgba64 unpremultiplied_64bit() const
{
@@ -188,10 +188,10 @@ private:
return *this;
const quint64 a = alpha();
const quint64 fa = (Q_UINT64_C(0xffff00008000) + a/2) / a;
- const quint16 r = (red() * fa + 0x80000000) >> 32;
- const quint16 g = (green() * fa + 0x80000000) >> 32;
- const quint16 b = (blue() * fa + 0x80000000) >> 32;
- return fromRgba64(r, g, b, a);
+ const quint16 r = quint16((red() * fa + 0x80000000) >> 32);
+ const quint16 g = quint16((green() * fa + 0x80000000) >> 32);
+ const quint16 b = quint16((blue() * fa + 0x80000000) >> 32);
+ return fromRgba64(r, g, b, quint16(a));
}
};