diff options
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/qbrush.cpp | 8 | ||||
-rw-r--r-- | src/gui/painting/qbrush.h | 4 | ||||
-rw-r--r-- | src/gui/painting/qcolor.cpp | 7 | ||||
-rw-r--r-- | src/gui/painting/qcolor.h | 42 | ||||
-rw-r--r-- | src/gui/painting/qcolorspace_p.h | 2 | ||||
-rw-r--r-- | src/gui/painting/qcolortransform.cpp | 4 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 37 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 56 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 28 | ||||
-rw-r--r-- | src/gui/painting/qpainter.h | 6 | ||||
-rw-r--r-- | src/gui/painting/qpainter_p.h | 1 | ||||
-rw-r--r-- | src/gui/painting/qpainterpath.cpp | 62 | ||||
-rw-r--r-- | src/gui/painting/qpainterpath_p.h | 4 | ||||
-rw-r--r-- | src/gui/painting/qpen.cpp | 6 | ||||
-rw-r--r-- | src/gui/painting/qstroker.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qtextureglyphcache.cpp | 8 |
16 files changed, 173 insertions, 104 deletions
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 21e41979af..abb3268dfa 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -352,7 +352,7 @@ public: QBrushData *brush; QNullBrushData() : brush(new QBrushData) { - brush->ref.store(1); + brush->ref.storeRelaxed(1); brush->style = Qt::BrushStyle(0); brush->color = Qt::black; } @@ -411,7 +411,7 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style) d.reset(new QBrushData); break; } - d->ref.store(1); + d->ref.storeRelaxed(1); d->style = style; d->color = color; } @@ -585,7 +585,7 @@ static Q_DECL_CONSTEXPR inline bool use_same_brushdata(Qt::BrushStyle lhs, Qt::B void QBrush::detach(Qt::BrushStyle newStyle) { - if (use_same_brushdata(newStyle, d->style) && d->ref.load() == 1) { + if (use_same_brushdata(newStyle, d->style) && d->ref.loadRelaxed() == 1) { d->style = newStyle; return; } @@ -625,7 +625,7 @@ void QBrush::detach(Qt::BrushStyle newStyle) x.reset(new QBrushData); break; } - x->ref.store(1); // must be first lest the QBrushDataPointerDeleter turns into a no-op + x->ref.storeRelaxed(1); // must be first lest the QBrushDataPointerDeleter turns into a no-op x->style = newStyle; x->color = d->color; x->transform = d->transform; diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index ca51430cf4..6a4ffab1c5 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -159,7 +159,7 @@ inline Qt::BrushStyle QBrush::style() const { return d->style; } inline const QColor &QBrush::color() const { return d->color; } inline const QMatrix &QBrush::matrix() const { return d->transform.toAffine(); } inline QTransform QBrush::transform() const { return d->transform; } -inline bool QBrush::isDetached() const { return d->ref.load() == 1; } +inline bool QBrush::isDetached() const { return d->ref.loadRelaxed() == 1; } /******************************************************************************* @@ -371,6 +371,8 @@ public: GagarinView = 178, FabledSunset = 179, PerfectBlue = 180, + + NumPresets }; Q_ENUM(Preset) diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 174350d884..6cbc30e79a 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -1349,7 +1349,7 @@ void QColor::setRgbF(qreal r, qreal g, qreal b, qreal a) */ void QColor::setRgb(int r, int g, int b, int a) { - if ((uint)r > 255 || (uint)g > 255 || (uint)b > 255 || (uint)a > 255) { + if (!isRgbaValid(r, g, b, a)) { qWarning("QColor::setRgb: RGB parameters out of range"); invalidate(); return; @@ -2398,10 +2398,7 @@ QColor QColor::fromRgba(QRgb rgba) noexcept */ QColor QColor::fromRgb(int r, int g, int b, int a) { - if (r < 0 || r > 255 - || g < 0 || g > 255 - || b < 0 || b > 255 - || a < 0 || a > 255) { + if (!isRgbaValid(r, g, b, a)) { qWarning("QColor::fromRgb: RGB parameters out of range"); return QColor(); } diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h index e3c267f97d..723b9fce73 100644 --- a/src/gui/painting/qcolor.h +++ b/src/gui/painting/qcolor.h @@ -67,9 +67,16 @@ public: enum Spec { Invalid, Rgb, Hsv, Cmyk, Hsl, ExtendedRgb }; enum NameFormat { HexRgb, HexArgb }; - inline QColor() noexcept; + Q_DECL_CONSTEXPR QColor() noexcept + : cspec(Invalid), ct(USHRT_MAX, 0, 0, 0, 0) {} QColor(Qt::GlobalColor color) noexcept; - inline QColor(int r, int g, int b, int a = 255); + Q_DECL_CONSTEXPR QColor(int r, int g, int b, int a = 255) noexcept + : cspec(isRgbaValid(r, g, b, a) ? Rgb : Invalid), + ct(cspec == Rgb ? a * 0x0101 : 0, + cspec == Rgb ? r * 0x0101 : 0, + cspec == Rgb ? g * 0x0101 : 0, + cspec == Rgb ? b * 0x0101 : 0, + 0) {} QColor(QRgb rgb) noexcept; QColor(QRgba64 rgba64) noexcept; #if QT_STRINGVIEW_LEVEL < 2 @@ -81,8 +88,11 @@ public: QColor(Spec spec) noexcept; #if QT_VERSION < QT_VERSION_CHECK(6,0,0) - inline QColor(const QColor &color) noexcept; // ### Qt 6: remove all of these, the trivial ones are fine. - QColor(QColor &&other) noexcept : cspec(other.cspec), ct(other.ct) {} + // ### Qt 6: remove all of these, the trivial ones are fine. + Q_DECL_CONSTEXPR QColor(const QColor &color) noexcept + : cspec(color.cspec), ct(color.ct) + {} + Q_DECL_CONSTEXPR QColor(QColor &&other) noexcept : cspec(other.cspec), ct(other.ct) {} QColor &operator=(QColor &&other) noexcept { cspec = other.cspec; ct = other.ct; return *this; } QColor &operator=(const QColor &) noexcept; @@ -244,8 +254,18 @@ private: template <typename String> bool setColorFromString(String name); + static Q_DECL_CONSTEXPR bool isRgbaValid(int r, int g, int b, int a = 255) noexcept Q_DECL_CONST_FUNCTION + { + return uint(r) <= 255 && uint(g) <= 255 && uint(b) <= 255 && uint(a) <= 255; + } + Spec cspec; - union { + union CT { +#ifdef Q_COMPILER_UNIFORM_INIT + CT() {} // doesn't init anything, thus can't be constexpr + Q_DECL_CONSTEXPR explicit CT(ushort a1, ushort a2, ushort a3, ushort a4, ushort a5) noexcept + : array{a1, a2, a3, a4, a5} {} +#endif struct { ushort alpha; ushort red; @@ -292,12 +312,6 @@ private: }; Q_DECLARE_TYPEINFO(QColor, QT_VERSION >= QT_VERSION_CHECK(6,0,0) ? Q_MOVABLE_TYPE : Q_RELOCATABLE_TYPE); -inline QColor::QColor() noexcept -{ invalidate(); } - -inline QColor::QColor(int r, int g, int b, int a) -{ setRgb(r, g, b, a); } - inline QColor::QColor(QLatin1String aname) { setNamedColor(aname); } @@ -309,12 +323,6 @@ inline QColor::QColor(const QString& aname) { setNamedColor(aname); } #endif -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) -inline QColor::QColor(const QColor &acolor) noexcept - : cspec(acolor.cspec) -{ ct.argb = acolor.ct.argb; } -#endif - inline bool QColor::isValid() const noexcept { return cspec != Invalid; } diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h index a49c46f195..95e0655d0c 100644 --- a/src/gui/painting/qcolorspace_p.h +++ b/src/gui/painting/qcolorspace_p.h @@ -123,7 +123,7 @@ public: table[0] = other.table[0]; table[1] = other.table[1]; table[2] = other.table[2]; - generated.store(1); + generated.storeRelaxed(1); } } QSharedPointer<QColorTrcLut> &operator[](int i) { return table[i]; } diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp index 2f81449693..de08bf4221 100644 --- a/src/gui/painting/qcolortransform.cpp +++ b/src/gui/painting/qcolortransform.cpp @@ -71,7 +71,7 @@ void QColorTransformPrivate::updateLutsIn() const if (colorSpaceIn->lut.generated.loadAcquire()) return; QMutexLocker lock(&QColorSpacePrivate::s_lutWriteLock); - if (colorSpaceIn->lut.generated.load()) + if (colorSpaceIn->lut.generated.loadRelaxed()) return; for (int i = 0; i < 3; ++i) { @@ -96,7 +96,7 @@ void QColorTransformPrivate::updateLutsOut() const if (colorSpaceOut->lut.generated.loadAcquire()) return; QMutexLocker lock(&QColorSpacePrivate::s_lutWriteLock); - if (colorSpaceOut->lut.generated.load()) + if (colorSpaceOut->lut.generated.loadRelaxed()) return; for (int i = 0; i < 3; ++i) { if (!colorSpaceOut->trc[i].isValid()) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index ac15d8f4f4..006befea22 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -4566,7 +4566,9 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) if (mode == QPainter::CompositionMode_Source) { // inline for performance ushort c = data->solidColor.toRgb16(); - while (count--) { + for (; count--; spans++) { + if (!spans->len) + continue; ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; if (spans->coverage == 255) { qt_memfill(target, c, spans->len); @@ -4579,13 +4581,14 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) ++target; } } - ++spans; } return; } if (mode == QPainter::CompositionMode_SourceOver) { - while (count--) { + for (; count--; spans++) { + if (!spans->len) + continue; uint color = BYTE_MUL(data->solidColor.toArgb32(), spans->coverage); int ialpha = qAlpha(~color); ushort c = qConvertRgb32To16(color); @@ -4617,7 +4620,6 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) // one last pixel beyond a full word *target = c + BYTE_MUL_RGB16(*target, ialpha); } - ++spans; } return; } @@ -4634,6 +4636,11 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle int coverage = 0; while (count) { + if (!spans->len) { + ++spans; + --count; + continue; + } int x = spans->x; const int y = spans->y; int right = x + spans->len; @@ -4790,7 +4797,9 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use int xoff = -qRound(-data->dx); int yoff = -qRound(-data->dy); - while (count--) { + for (; count--; spans++) { + if (!spans->len) + continue; int x = spans->x; int length = spans->len; int sx = xoff + x; @@ -4818,7 +4827,6 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use } } } - ++spans; } } @@ -4840,7 +4848,9 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi int xoff = -qRound(-data->dx); int yoff = -qRound(-data->dy); - while (count--) { + for (; count--; spans++) { + if (!spans->len) + continue; int x = spans->x; int length = spans->len; int sx = xoff + x; @@ -4868,7 +4878,6 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi } } } - ++spans; } } #endif @@ -4889,7 +4898,9 @@ static void blend_untransformed_argb(int count, const QSpan *spans, void *userDa int xoff = -qRound(-data->dx); int yoff = -qRound(-data->dy); - while (count--) { + for (; count--; spans++) { + if (!spans->len) + continue; int x = spans->x; int length = spans->len; int sx = xoff + x; @@ -4909,7 +4920,6 @@ static void blend_untransformed_argb(int count, const QSpan *spans, void *userDa op.func(dest, src, length, coverage); } } - ++spans; } } @@ -4982,7 +4992,12 @@ static void blend_untransformed_rgb565(int count, const QSpan *spans, void *user int xoff = -qRound(-data->dx); int yoff = -qRound(-data->dy); - while (count--) { + const QSpan *end = spans + count; + while (spans < end) { + if (!spans->len) { + ++spans; + continue; + } const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; if (coverage == 0) { ++spans; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 85ddff53db..461ad51200 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -904,7 +904,11 @@ void QRasterPaintEngine::renderHintsChanged() bool was_aa = s->flags.antialiased; bool was_bilinear = s->flags.bilinear; - s->flags.antialiased = bool(s->renderHints & (QPainter::Antialiasing | QPainter::HighQualityAntialiasing)); + s->flags.antialiased = bool(s->renderHints & QPainter::Antialiasing); +#if QT_DEPRECATED_SINCE(5, 14) + if (s->renderHints & QPainter::HighQualityAntialiasing) + s->flags.antialiased = true; +#endif s->flags.bilinear = bool(s->renderHints & QPainter::SmoothPixmapTransform); s->flags.legacy_rounding = !bool(s->renderHints & QPainter::Antialiasing) && bool(s->renderHints & QPainter::Qt4CompatiblePainting); @@ -4149,7 +4153,7 @@ static void qt_span_fill_clipped(int spanCount, const QSpan *spans, void *userDa Clip spans to \a{clip}-rectangle. Returns number of unclipped spans */ -static int qt_intersect_spans(QT_FT_Span *spans, int numSpans, +static int qt_intersect_spans(QT_FT_Span *&spans, int numSpans, const QRect &clip) { const short minx = clip.left(); @@ -4157,29 +4161,32 @@ static int qt_intersect_spans(QT_FT_Span *spans, int numSpans, const short maxx = clip.right(); const short maxy = clip.bottom(); - int n = 0; - for (int i = 0; i < numSpans; ++i) { - if (spans[i].y > maxy) + QT_FT_Span *end = spans + numSpans; + while (spans < end) { + if (spans->y >= miny) + break; + ++spans; + } + + QT_FT_Span *s = spans; + while (s < end) { + if (s->y > maxy) break; - if (spans[i].y < miny - || spans[i].x > maxx - || spans[i].x + spans[i].len <= minx) { + if (s->x > maxx || s->x + s->len <= minx) { + s->len = 0; + ++s; continue; } - if (spans[i].x < minx) { - spans[n].len = qMin(spans[i].len - (minx - spans[i].x), maxx - minx + 1); - spans[n].x = minx; + if (s->x < minx) { + s->len = qMin(s->len - (minx - s->x), maxx - minx + 1); + s->x = minx; } else { - spans[n].x = spans[i].x; - spans[n].len = qMin(spans[i].len, ushort(maxx - spans[n].x + 1)); + s->len = qMin(s->len, ushort(maxx - s->x + 1)); } - if (spans[n].len == 0) - continue; - spans[n].y = spans[i].y; - spans[n].coverage = spans[i].coverage; - ++n; + ++s; } - return n; + + return s - spans; } @@ -4192,11 +4199,12 @@ static void qt_span_fill_clipRect(int count, const QSpan *spans, Q_ASSERT(fillData->clip); Q_ASSERT(!fillData->clip->clipRect.isEmpty()); + QSpan *s = const_cast<QSpan *>(spans); // hw: check if this const_cast<> is safe!!! - count = qt_intersect_spans(const_cast<QSpan*>(spans), count, + count = qt_intersect_spans(s, count, fillData->clip->clipRect); if (count > 0) - fillData->unclipped_blend(count, spans, fillData); + fillData->unclipped_blend(count, s, fillData); } static void qt_span_clip(int count, const QSpan *spans, void *userData) @@ -4773,7 +4781,8 @@ static inline void drawEllipsePoints(int x, int y, int length, if (length == 0) return; - QT_FT_Span outline[4]; + QT_FT_Span _outline[4]; + QT_FT_Span *outline = _outline; const int midx = rect.x() + (rect.width() + 1) / 2; const int midy = rect.y() + (rect.height() + 1) / 2; @@ -4805,7 +4814,8 @@ static inline void drawEllipsePoints(int x, int y, int length, outline[3].coverage = 255; if (brush_func && outline[0].x + outline[0].len < outline[1].x) { - QT_FT_Span fill[2]; + QT_FT_Span _fill[2]; + QT_FT_Span *fill = _fill; // top fill fill[0].x = outline[0].x + outline[0].len - 1; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 95e6bda78b..84b34e390b 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -283,7 +283,7 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev) Q_ASSERT(q->d_ptr->state); // Now initialize the painter with correct widget properties. - q->initFrom(pdev); + q->d_ptr->initFrom(pdev); QPoint offset; pdev->redirected(&offset); offset += q->d_ptr->engine->coordinateOffset(); @@ -1560,22 +1560,28 @@ void QPainter::initFrom(const QPaintDevice *device) { Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0"); Q_D(QPainter); - if (!d->engine) { + d->initFrom(device); +} +#endif + +void QPainterPrivate::initFrom(const QPaintDevice *device) +{ + if (!engine) { qWarning("QPainter::initFrom: Painter not active, aborted"); return; } - device->initPainter(this); + Q_Q(QPainter); + device->initPainter(q); - if (d->extended) { - d->extended->penChanged(); - } else if (d->engine) { - d->engine->setDirty(QPaintEngine::DirtyPen); - d->engine->setDirty(QPaintEngine::DirtyBrush); - d->engine->setDirty(QPaintEngine::DirtyFont); + if (extended) { + extended->penChanged(); + } else if (engine) { + engine->setDirty(QPaintEngine::DirtyPen); + engine->setDirty(QPaintEngine::DirtyBrush); + engine->setDirty(QPaintEngine::DirtyFont); } } -#endif /*! Saves the current painter state (pushes the state onto a stack). A @@ -1843,7 +1849,7 @@ bool QPainter::begin(QPaintDevice *pd) // Copy painter properties from original paint device, // required for QPixmap::grabWidget() if (d->original_device->devType() == QInternal::Widget) { - initFrom(d->original_device); + d->initFrom(d->original_device); } else { d->state->layoutDirection = Qt::LayoutDirectionAuto; // make sure we have a font compatible with the paintdevice diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 843f24e3e1..3394da63c7 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -89,8 +89,10 @@ public: Antialiasing = 0x01, TextAntialiasing = 0x02, SmoothPixmapTransform = 0x04, - HighQualityAntialiasing = 0x08, - NonCosmeticDefaultPen = 0x10, +#if QT_DEPRECATED_SINCE(5, 14) + HighQualityAntialiasing Q_DECL_ENUMERATOR_DEPRECATED_X("Use Antialiasing instead") = 0x08, + NonCosmeticDefaultPen Q_DECL_ENUMERATOR_DEPRECATED_X("Default pen is non-cosmetic now") = 0x10, +#endif Qt4CompatiblePainting = 0x20, LosslessImageRendering = 0x40, }; diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index bd2bc4c9b3..29d4880eb9 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -256,6 +256,7 @@ public: QTransform hidpiScaleTransform() const; static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev); void detachPainterPrivate(QPainter *q); + void initFrom(const QPaintDevice *device); QPaintDevice *device; QPaintDevice *original_device; diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 42872359d7..8801e66b0f 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -71,6 +71,24 @@ QT_BEGIN_NAMESPACE +static inline bool isValidCoord(qreal c) +{ + if (sizeof(qreal) >= sizeof(double)) + return qIsFinite(c) && fabs(c) < 1e128; + else + return qIsFinite(c) && fabsf(float(c)) < 1e16f; +} + +static bool hasValidCoords(QPointF p) +{ + return isValidCoord(p.x()) && isValidCoord(p.y()); +} + +static bool hasValidCoords(QRectF r) +{ + return isValidCoord(r.x()) && isValidCoord(r.y()) && isValidCoord(r.width()) && isValidCoord(r.height()); +} + struct QPainterPathPrivateDeleter { static inline void cleanup(QPainterPathPrivate *d) @@ -560,7 +578,7 @@ QPainterPath::QPainterPath(const QPointF &startPoint) void QPainterPath::detach() { - if (d_ptr->ref.load() != 1) + if (d_ptr->ref.loadRelaxed() != 1) detach_helper(); setDirty(true); } @@ -657,8 +675,9 @@ void QPainterPath::reserve(int size) { Q_D(QPainterPath); if ((!d && size > 0) || (d && d->elements.capacity() < size)) { + ensureData(); detach(); - d->elements.reserve(size); + d_func()->elements.reserve(size); } } @@ -724,9 +743,9 @@ void QPainterPath::moveTo(const QPointF &p) printf("QPainterPath::moveTo() (%.2f,%.2f)\n", p.x(), p.y()); #endif - if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) { + if (!hasValidCoords(p)) { #ifndef QT_NO_DEBUG - qWarning("QPainterPath::moveTo: Adding point where x or y is NaN or Inf, ignoring call"); + qWarning("QPainterPath::moveTo: Adding point with invalid coordinates, ignoring call"); #endif return; } @@ -774,9 +793,9 @@ void QPainterPath::lineTo(const QPointF &p) printf("QPainterPath::lineTo() (%.2f,%.2f)\n", p.x(), p.y()); #endif - if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) { + if (!hasValidCoords(p)) { #ifndef QT_NO_DEBUG - qWarning("QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call"); + qWarning("QPainterPath::lineTo: Adding point with invalid coordinates, ignoring call"); #endif return; } @@ -833,10 +852,9 @@ void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF & c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); #endif - if (!qt_is_finite(c1.x()) || !qt_is_finite(c1.y()) || !qt_is_finite(c2.x()) || !qt_is_finite(c2.y()) - || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) { + if (!hasValidCoords(c1) || !hasValidCoords(c2) || !hasValidCoords(e)) { #ifndef QT_NO_DEBUG - qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN or Inf, ignoring call"); + qWarning("QPainterPath::cubicTo: Adding point with invalid coordinates, ignoring call"); #endif return; } @@ -890,9 +908,9 @@ void QPainterPath::quadTo(const QPointF &c, const QPointF &e) c.x(), c.y(), e.x(), e.y()); #endif - if (!qt_is_finite(c.x()) || !qt_is_finite(c.y()) || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) { + if (!hasValidCoords(c) || !hasValidCoords(e)) { #ifndef QT_NO_DEBUG - qWarning("QPainterPath::quadTo: Adding point where x or y is NaN or Inf, ignoring call"); + qWarning("QPainterPath::quadTo: Adding point with invalid coordinates, ignoring call"); #endif return; } @@ -961,10 +979,9 @@ void QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength rect.x(), rect.y(), rect.width(), rect.height(), startAngle, sweepLength); #endif - if ((!qt_is_finite(rect.x()) && !qt_is_finite(rect.y())) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height()) - || !qt_is_finite(startAngle) || !qt_is_finite(sweepLength)) { + if (!hasValidCoords(rect) || !isValidCoord(startAngle) || !isValidCoord(sweepLength)) { #ifndef QT_NO_DEBUG - qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN or Inf, ignoring call"); + qWarning("QPainterPath::arcTo: Adding point with invalid coordinates, ignoring call"); #endif return; } @@ -1067,9 +1084,9 @@ QPointF QPainterPath::currentPosition() const */ void QPainterPath::addRect(const QRectF &r) { - if (!qt_is_finite(r.x()) || !qt_is_finite(r.y()) || !qt_is_finite(r.width()) || !qt_is_finite(r.height())) { + if (!hasValidCoords(r)) { #ifndef QT_NO_DEBUG - qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN or Inf, ignoring call"); + qWarning("QPainterPath::addRect: Adding point with invalid coordinates, ignoring call"); #endif return; } @@ -1147,10 +1164,9 @@ void QPainterPath::addPolygon(const QPolygonF &polygon) */ void QPainterPath::addEllipse(const QRectF &boundingRect) { - if (!qt_is_finite(boundingRect.x()) || !qt_is_finite(boundingRect.y()) - || !qt_is_finite(boundingRect.width()) || !qt_is_finite(boundingRect.height())) { + if (!hasValidCoords(boundingRect)) { #ifndef QT_NO_DEBUG - qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN or Inf, ignoring call"); + qWarning("QPainterPath::addEllipse: Adding point with invalid coordinates, ignoring call"); #endif return; } @@ -2501,6 +2517,7 @@ QDataStream &operator<<(QDataStream &s, const QPainterPath &p) */ QDataStream &operator>>(QDataStream &s, QPainterPath &p) { + bool errorDetected = false; int size; s >> size; @@ -2519,10 +2536,11 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p) s >> x; s >> y; Q_ASSERT(type >= 0 && type <= 3); - if (!qt_is_finite(x) || !qt_is_finite(y)) { + if (!isValidCoord(qreal(x)) || !isValidCoord(qreal(y))) { #ifndef QT_NO_DEBUG - qWarning("QDataStream::operator>>: NaN or Inf element found in path, skipping it"); + qWarning("QDataStream::operator>>: Invalid QPainterPath coordinates read, skipping it"); #endif + errorDetected = true; continue; } QPainterPath::Element elm = { qreal(x), qreal(y), QPainterPath::ElementType(type) }; @@ -2535,6 +2553,8 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p) p.d_func()->fillRule = Qt::FillRule(fillRule); p.d_func()->dirtyBounds = true; p.d_func()->dirtyControlBounds = true; + if (errorDetected) + p = QPainterPath(); // Better than to return path with possibly corrupt datastructure, which would likely cause crash return s; } #endif // QT_NO_DATASTREAM diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h index 4eb541ec65..22bdbde2a9 100644 --- a/src/gui/painting/qpainterpath_p.h +++ b/src/gui/painting/qpainterpath_p.h @@ -281,7 +281,7 @@ inline bool QPainterPathData::isClosed() const inline void QPainterPathData::close() { - Q_ASSERT(ref.load() == 1); + Q_ASSERT(ref.loadRelaxed() == 1); require_moveTo = true; const QPainterPath::Element &first = elements.at(cStart); QPainterPath::Element &last = elements.last(); @@ -308,7 +308,7 @@ inline void QPainterPathData::maybeMoveTo() inline void QPainterPathData::clear() { - Q_ASSERT(ref.load() == 1); + Q_ASSERT(ref.loadRelaxed() == 1); elements.clear(); diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp index 58a1716037..dc6e3e04d0 100644 --- a/src/gui/painting/qpen.cpp +++ b/src/gui/painting/qpen.cpp @@ -363,13 +363,13 @@ QPen::~QPen() void QPen::detach() { - if (d->ref.load() == 1) + if (d->ref.loadRelaxed() == 1) return; QPenData *x = new QPenData(*static_cast<QPenData *>(d)); if (!d->ref.deref()) delete d; - x->ref.store(1); + x->ref.storeRelaxed(1); d = x; } @@ -885,7 +885,7 @@ bool QPen::operator==(const QPen &p) const bool QPen::isDetached() { - return d->ref.load() == 1; + return d->ref.loadRelaxed() == 1; } diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index 5b6990e667..271d3ba6bf 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -522,7 +522,7 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine QLineF shortCut(prevLine.p2(), nextLine.p1()); qreal angle = shortCut.angleTo(prevLine); - if (type == QLineF::BoundedIntersection || (angle > 90 && !qFuzzyCompare(angle, (qreal)90))) { + if ((type == QLineF::BoundedIntersection || (angle > qreal(90.01))) && nextLine.length() > offset) { emitLineTo(focal_x, focal_y); emitLineTo(qt_real_to_fixed(nextLine.x1()), qt_real_to_fixed(nextLine.y1())); return; diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index c21f2cdda4..e8c47df21c 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -285,6 +285,8 @@ QImageTextureGlyphCache::~QImageTextureGlyphCache() void QImageTextureGlyphCache::resizeTextureData(int width, int height) { m_image = m_image.copy(0, 0, width, height); + // Regions not part of the copy are initialized to 0, and that is just what + // we need. } void QImageTextureGlyphCache::createTextureData(int width, int height) @@ -305,6 +307,12 @@ void QImageTextureGlyphCache::createTextureData(int width, int height) default: Q_UNREACHABLE(); } + + // Regions not touched by the glyphs must be initialized to 0. (such + // locations may in fact be sampled with styled (shifted) text materials) + // When resizing, the QImage copy() does this implicitly but the initial + // contents must be zeroed out explicitly here. + m_image.fill(0); } void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subPixelPosition) |