diff options
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/qoutlinemapper.cpp | 21 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 21 | ||||
-rw-r--r-- | src/gui/painting/qpainter.h | 1 | ||||
-rw-r--r-- | src/gui/painting/qpdf.cpp | 8 | ||||
-rw-r--r-- | src/gui/painting/qregion.cpp | 10 | ||||
-rw-r--r-- | src/gui/painting/qrgba64.h | 38 |
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 ®ion) { 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)); } }; |