diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/painting/qdatabuffer_p.h | 17 | ||||
-rw-r--r-- | src/gui/painting/qoutlinemapper.cpp | 59 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 89 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster_p.h | 2 | ||||
-rw-r--r-- | src/gui/painting/qpaintengineex.cpp | 68 | ||||
-rw-r--r-- | src/gui/painting/qpainterpath.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qvectorpath_p.h | 2 |
7 files changed, 122 insertions, 117 deletions
diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h index 275ec13..b568f43 100644 --- a/src/gui/painting/qdatabuffer_p.h +++ b/src/gui/painting/qdatabuffer_p.h @@ -114,6 +114,23 @@ public: qSwap(buffer, other.buffer); } + inline void insertBlank(int pos, int count) { + Q_ASSERT(pos >= 0); + Q_ASSERT(pos < siz); + reserve(siz + count); + for (int i = siz - pos - 1; i >= 0; --i) + buffer[pos + count + i] = buffer[pos + i]; + siz += count; + } + + inline void removeAndShift(int pos, int count) { + Q_ASSERT(pos >= 0); + Q_ASSERT(pos < siz); + for (int i=pos; i<siz-count; ++i) + buffer[i] = buffer[i+count]; + siz -= count; + } + inline QDataBuffer &operator<<(const Type &t) { add(t); return *this; } private: diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index 401fad9..9c073f2 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qoutlinemapper_p.h" +#include "qbezier_p.h" #include "qmath.h" @@ -199,51 +200,69 @@ void QOutlineMapper::endOutline() } } else { // ## TODO: this case needs to be plain code polygonal paths - QPainterPath path; + QTransform matrix(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33); + if (m_element_types.isEmpty()) { if (!m_elements.isEmpty()) - path.moveTo(m_elements.at(0)); + m_elements_dev << m_elements.at(0) * matrix; for (int i=1; i<m_elements.size(); ++i) - path.lineTo(m_elements.at(i)); + m_elements_dev << m_elements.at(i) * matrix; + } else { - for (int i=0; i<m_elements.size(); ++i) { - switch (m_element_types.at(i)) { + for (int i=0, t=0; i<m_elements.size(); ++i) { + switch (m_element_types.at(t)) { case QPainterPath::MoveToElement: - path.moveTo(m_elements.at(i)); + m_elements_dev << m_elements.at(i) * matrix; + ++t; break; case QPainterPath::LineToElement: - path.lineTo(m_elements.at(i)); + m_elements_dev << m_elements.at(i) * matrix; + ++t; break; - case QPainterPath::CurveToElement: - path.cubicTo(m_elements.at(i), m_elements.at(i+1), m_elements.at(i+2)); + case QPainterPath::CurveToElement: { + QPolygonF segment = QBezier::fromPoints(m_elements.at(i-1), + m_elements.at(i), + m_elements.at(i+1), + m_elements.at(i+2)).toPolygon(); + if (segment.size() > 3) + m_element_types.insertBlank(t, segment.size() - 3); + else if (segment.size() < 3) + m_element_types.removeAndShift(t, 3 - segment.size()); + + for (QPolygonF::const_iterator it = segment.constBegin(); + it < segment.constEnd(); ++it, ++t) { + m_elements_dev << *it * matrix; + m_element_types.at(t) = QPainterPath::LineToElement; + } i += 2; - break; + } break; default: Q_ASSERT(false); break; } } + element_count = m_elements_dev.size(); } - path = QTransform(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33).map(path); - uint old_txop = m_txop; - m_txop = QTransform::TxNone; - if (path.isEmpty()) - m_valid = false; - else - convertPath(path); - m_txop = old_txop; - return; } elements = m_elements_dev.data(); } if (m_round_coords) { // round coordinates to match outlines drawn with drawLine_midpoint_i - for (int i = 0; i < m_elements.size(); ++i) + for (int i = 0; i < element_count; ++i) elements[i] = QPointF(qFloor(elements[i].x() + aliasedCoordinateDelta), qFloor(elements[i].y() + aliasedCoordinateDelta)); } +#ifdef QT_DEBUG_CONVERT + for (int i=0; i<element_count; ++i) { + printf("%d: (%.2f, %.2f)\n", + !m_element_types.isEmpty() ? m_element_types.at(i) : -1, + elements[i].x(), + elements[i].y()); + } +#endif + controlPointRect = boundingRect(elements, element_count); #ifdef QT_DEBUG_CONVERT diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index dfd3e16..69e490a 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1672,34 +1672,6 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount) QPaintEngineEx::drawRects(rects, rectCount); } -void QRasterPaintEnginePrivate::strokeProjective(const QPainterPath &path) -{ - Q_Q(QRasterPaintEngine); - QRasterPaintEngineState *s = q->state(); - - const QPen &pen = s->lastPen; - QPainterPathStroker pathStroker; - pathStroker.setWidth(pen.width() == 0 ? qreal(1) : pen.width()); - pathStroker.setCapStyle(pen.capStyle()); - pathStroker.setJoinStyle(pen.joinStyle()); - pathStroker.setMiterLimit(pen.miterLimit()); - pathStroker.setDashOffset(pen.dashOffset()); - - if (qpen_style(pen) == Qt::CustomDashLine) - pathStroker.setDashPattern(pen.dashPattern()); - else - pathStroker.setDashPattern(qpen_style(pen)); - - outlineMapper->setMatrix(QTransform()); - const QPainterPath stroke = pen.isCosmetic() - ? pathStroker.createStroke(s->matrix.map(path)) - : s->matrix.map(pathStroker.createStroke(path)); - - rasterize(outlineMapper->convertPath(stroke), s->penData.blend, &s->penData, rasterBuffer); - outlinemapper_xform_dirty = true; -} - - /*! \internal @@ -1969,67 +1941,6 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) fillRect(r, &d->solid_color_filler); } -/*! - \reimp -*/ -void QRasterPaintEngine::drawPath(const QPainterPath &path) -{ -#ifdef QT_DEBUG_DRAW - QRectF bounds = path.boundingRect(); - qDebug(" - QRasterPaintEngine::drawPath(), [%.2f, %.2f, %.2f, %.2f]", - bounds.x(), bounds.y(), bounds.width(), bounds.height()); -#endif - - if (path.isEmpty()) - return; - - // Filling.., - Q_D(QRasterPaintEngine); - QRasterPaintEngineState *s = state(); - - ensureBrush(); - if (s->brushData.blend) { - ensureOutlineMapper(); - fillPath(path, &s->brushData); - } - - // Stroking... - ensurePen(); - if (!s->penData.blend) - return; - { - if (s->matrix.type() >= QTransform::TxProject) { - d->strokeProjective(path); - } else { - Q_ASSERT(s->stroker); - d->outlineMapper->beginOutline(Qt::WindingFill); - qreal txscale = 1; - if (s->pen.isCosmetic() || (qt_scaleForTransform(s->matrix, &txscale) && txscale != 1)) { - const qreal strokeWidth = d->basicStroker.strokeWidth(); - const QRectF clipRect = d->dashStroker ? d->dashStroker->clipRect() : QRectF(); - if (d->dashStroker) - d->dashStroker->setClipRect(d->deviceRect); - d->basicStroker.setStrokeWidth(strokeWidth * txscale); - d->outlineMapper->setMatrix(QTransform()); - s->stroker->strokePath(path, d->outlineMapper, s->matrix); - d->outlinemapper_xform_dirty = true; - d->basicStroker.setStrokeWidth(strokeWidth); - if (d->dashStroker) - d->dashStroker->setClipRect(clipRect); - } else { - ensureOutlineMapper(); - s->stroker->strokePath(path, d->outlineMapper, QTransform()); - } - d->outlineMapper->endOutline(); - - ProcessSpans blend = d->getPenFunc(d->outlineMapper->controlPointRect, - &s->penData); - d->rasterize(d->outlineMapper->outline(), blend, &s->penData, d->rasterBuffer); - } - } - -} - static inline bool isAbove(const QPointF *a, const QPointF *b) { return a->y() < b->y(); diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 283c442..3dab491 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -165,7 +165,6 @@ public: void updateMatrix(const QTransform &matrix); - void drawPath(const QPainterPath &path); void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); void fillPath(const QPainterPath &path, QSpanData *fillData); @@ -327,7 +326,6 @@ public: inline const QClipData *clip() const; - void strokeProjective(const QPainterPath &path); void initializeRasterizer(QSpanData *data); void recalculateFastImages(); diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 797a5ab..8ec881e 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -42,6 +42,7 @@ #include "qpaintengineex_p.h" #include "qpainter_p.h" #include "qstroker_p.h" +#include "qbezier_p.h" #include <private/qpainterpath_p.h> #include <qvarlengtharray.h> @@ -91,6 +92,40 @@ QRectF QVectorPath::controlPointRect() const return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2)); } +QPainterPath QVectorPath::convertToPainterPath() const +{ + QPainterPath path; + + if (m_count == 0) + return path; + + const QPointF *points = (const QPointF *) m_points; + + if (m_elements) { + for (int i=0; i<m_count; ++i) { + switch (m_elements[i]) { + case QPainterPath::MoveToElement: + path.moveTo(points[i]); + break; + case QPainterPath::LineToElement: + path.lineTo(points[i]); + break; + case QPainterPath::CurveToElement: + path.cubicTo(points[i], points[i+1], points[i+2]); + break; + default: + break; + } + } + } else { + path.moveTo(points[0]); + for (int i=1; i<m_count; ++i) + path.lineTo(points[i]); + } + + return path; +} + const QVectorPath &qtVectorPathForPath(const QPainterPath &path) { Q_ASSERT(path.d_func()); @@ -450,13 +485,14 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) QVectorPath strokePath(d->strokeHandler->pts.data(), d->strokeHandler->types.size(), d->strokeHandler->types.data(), - QVectorPath::WindingFill); + flags); fill(strokePath, pen.brush()); } else { const qreal strokeWidth = d->stroker.strokeWidth(); d->stroker.setStrokeWidth(strokeWidth * txscale); // For cosmetic pens we need a bit of trickery... We to process xform the input points if (types) { + bool isProject = state()->matrix.type() >= QTransform::TxProject; while (points < lastPoint) { switch (*types) { case QPainterPath::MoveToElement: { @@ -474,10 +510,30 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) break; } case QPainterPath::CurveToElement: { - QPointF c1 = ((QPointF *) points)[0] * state()->matrix; - QPointF c2 = ((QPointF *) points)[1] * state()->matrix; - QPointF e = ((QPointF *) points)[2] * state()->matrix; - d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); + // Convert projective xformed curves to line + // segments so they can be transformed more + // accurately + if (isProject) { + // -1 access here is safe because there is + // always an element prior to the cubicTo, we + // just need the value.. + QPolygonF segment = + QBezier::fromPoints(*(((QPointF *) points) - 1), + *((QPointF *) points), + *(((QPointF *) points) + 1), + *(((QPointF *) points) + 2)).toPolygon(); + + for (QPolygonF::const_iterator it = segment.constBegin(); + it < segment.constEnd(); ++it) { + const QPointF pt = *it * state()->matrix; + d->activeStroker->lineTo(pt.x(), pt.y()); + } + } else { + QPointF c1 = ((QPointF *) points)[0] * state()->matrix; + QPointF c2 = ((QPointF *) points)[1] * state()->matrix; + QPointF e = ((QPointF *) points)[2] * state()->matrix; + d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); + } points += 6; types += 3; flags |= QVectorPath::CurvedShapeHint; @@ -512,7 +568,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) QVectorPath strokePath(d->strokeHandler->pts.data(), d->strokeHandler->types.size(), d->strokeHandler->types.data(), - QVectorPath::WindingFill); + flags); QTransform xform = state()->matrix; state()->matrix = QTransform(); diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index ea86cf5..09972b0 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -3271,6 +3271,8 @@ void QPainterPath::setDirty(bool dirty) { d_func()->dirtyBounds = dirty; d_func()->dirtyControlBounds = dirty; + delete d_func()->pathConverter; + d_func()->pathConverter = 0; } void QPainterPath::computeBoundingRect() const diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h index b6b85fa..9264c9c 100644 --- a/src/gui/painting/qvectorpath_p.h +++ b/src/gui/painting/qvectorpath_p.h @@ -130,6 +130,8 @@ public: static inline uint polygonFlags(QPaintEngine::PolygonDrawMode mode); + QPainterPath convertToPainterPath() const; + private: Q_DISABLE_COPY(QVectorPath) |