diff options
author | Jason Barron <jbarron@trolltech.com> | 2009-08-04 08:33:52 (GMT) |
---|---|---|
committer | Jason Barron <jbarron@trolltech.com> | 2009-08-04 09:02:17 (GMT) |
commit | 4aafbd6222e7aeafd59a4a4356ba8c53b2bfa1d1 (patch) | |
tree | b34985c5716d98f01b9f36fd4a98f2ac9710099f /src/gui/painting | |
parent | a0df97c03f26a38af17a42fb44ad6910536c8857 (diff) | |
parent | 2076f150995e541308b1d8da936b3e12ab68b886 (diff) | |
download | Qt-4aafbd6222e7aeafd59a4a4356ba8c53b2bfa1d1.zip Qt-4aafbd6222e7aeafd59a4a4356ba8c53b2bfa1d1.tar.gz Qt-4aafbd6222e7aeafd59a4a4356ba8c53b2bfa1d1.tar.bz2 |
Merge commit 'qt/master-stable'
Conflicts:
config.tests/unix/openssl/openssl.pri
demos/embedded/embedded.pro
examples/itemviews/chart/chart.pro
examples/network/network.pro
examples/painting/painterpaths/painterpaths.pro
examples/threads/mandelbrot/mandelbrot.pro
qmake/project.cpp
src/3rdparty/libtiff/libtiff/tif_config.h
src/corelib/arch/arch.pri
src/corelib/global/qglobal.cpp
src/corelib/kernel/kernel.pri
src/corelib/kernel/qcore_unix_p.h
src/corelib/kernel/qobject.cpp
src/corelib/thread/qthread_unix.cpp
src/corelib/tools/qsharedpointer_impl.h
src/corelib/tools/tools.pri
src/gui/kernel/qaction.h
src/gui/kernel/qapplication.cpp
src/gui/painting/qregion.h
src/gui/widgets/qlineedit.cpp
src/gui/widgets/qlineedit_p.h
src/network/socket/qnativesocketengine_unix.cpp
tests/auto/qdir/tst_qdir.cpp
tests/auto/qdiriterator/tst_qdiriterator.cpp
tests/auto/qhttp/qhttp.pro
tests/auto/qline/qline.pro
tests/auto/qnetworkreply/tst_qnetworkreply.cpp
tests/auto/qresourceengine/qresourceengine.pro
tests/auto/qsharedpointer/qsharedpointer.pro
tests/auto/qstring/qstring.pro
tests/auto/qtcpsocket/qtcpsocket.pro
tests/auto/qtcpsocket/tst_qtcpsocket.cpp
Diffstat (limited to 'src/gui/painting')
22 files changed, 302 insertions, 830 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index d153215..4121be6 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -101,8 +101,8 @@ win32 { painting/qcolormap_win.cpp \ painting/qpaintdevice_win.cpp \ painting/qprintengine_win.cpp \ - painting/qprinterinfo_win.cpp \ - painting/qregion_win.cpp + painting/qprinterinfo_win.cpp + !win32-borland:!wince*:LIBS += -lmsimg32 } @@ -127,10 +127,6 @@ embedded { painting/qwindowsurface_raster.cpp \ } -wince* { - SOURCES -= painting/qregion_win.cpp -} - unix:x11 { HEADERS += \ painting/qpaintengine_x11_p.h diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 405acb7..40c9bf2 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -39,6 +39,9 @@ ** ****************************************************************************/ + +#include "qplatformdefs.h" + #include "qbackingstore_p.h" #include <QtCore/qglobal.h> diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index 831d389..fc2eb60 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -223,8 +223,8 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl, int h = ty2 - ty1; int w = tx2 - tx1; - const int dstx = int((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix); - const int dsty = int((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy); + const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; + const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; quint32 basex = quint32((sx < 0 ? srcRect.right() : srcRect.left()) * 65536) + dstx; quint32 srcy = quint32((sy < 0 ? srcRect.bottom() : srcRect.top()) * 65536) + dsty; @@ -723,8 +723,8 @@ template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl, int h = ty2 - ty1; int w = tx2 - tx1; - const int dstx = int((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix); - const int dsty = int((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy); + const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; + const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; quint32 basex = quint32((sx < 0 ? srcRect.right() : srcRect.left()) * 65536) + dstx; quint32 srcy = quint32((sy < 0 ? srcRect.bottom() : srcRect.top()) * 65536) + dsty; diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index 5479305..fdb3a8a 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -52,6 +52,15 @@ #include <QtGui/qimage.h> #include <QtGui/qpixmap.h> +#if defined(Q_OS_VXWORKS) +# if defined(m_data) +# undef m_data +# endif +# if defined(m_type) +# undef m_type +# endif +#endif + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index a70923d..d77ed57 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -4954,30 +4954,60 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void * if (sy < 0) sy += image_height; - while (length) { - int l = qMin(image_width - sx, length); - if (buffer_size < l) - l = buffer_size; - - DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; - const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; - if (modeSource && coverage == 255) { + if (modeSource && coverage == 255) { + // Copy the first texture block + length = image_width; + while (length) { + int l = qMin(image_width - sx, length); + if (buffer_size < l) + l = buffer_size; + DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; + const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; qt_memconvert<DST, SRC>(dest, src, l); - } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest24(dest, src, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest16(dest, src, coverage, l); - } else { - blendUntransformed_unaligned(dest, src, coverage, l); + length -= l; + sx = 0; } - x += l; - length -= l; - sx = 0; + // Now use the rasterBuffer as the source of the texture, + // We can now progressively copy larger blocks + // - Less cpu time in code figuring out what to copy + // We are dealing with one block of data + // - More likely to fit in the cache + // - can use memcpy + int copy_image_width = image_width; + length = spans->len - image_width; + DST *src = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; + DST *dest = src + copy_image_width; + while (copy_image_width < length) { + qt_memconvert(dest, src, copy_image_width); + dest += copy_image_width; + length -= copy_image_width; + copy_image_width *= 2; + } + qt_memconvert(dest, src, length); + } else { + while (length) { + int l = qMin(image_width - sx, length); + if (buffer_size < l) + l = buffer_size; + DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; + const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; + if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && + (quintptr(dest) & 3) == (quintptr(src) & 3)) + { + blendUntransformed_dest24(dest, src, coverage, l); + } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && + (quintptr(dest) & 3) == (quintptr(src) & 3)) + { + blendUntransformed_dest16(dest, src, coverage, l); + } else { + blendUntransformed_unaligned(dest, src, coverage, l); + } + + x += l; + length -= l; + sx = 0; + } } ++spans; } diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c index 888fd9a..6ab7055 100644 --- a/src/gui/painting/qgrayraster.c +++ b/src/gui/painting/qgrayraster.c @@ -134,7 +134,9 @@ #define ErrRaster_MemoryOverflow -4 - +#if defined(VXWORKS) +# include <vxWorksCommon.h> /* needed for setjmp.h */ +#endif #include <string.h> /* for qt_ft_memcpy() */ #include <setjmp.h> #include <limits.h> diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index 401fad9..70125b9 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -198,32 +198,8 @@ void QOutlineMapper::endOutline() m_m22 * e.y() + m_m12 * e.x() + m_dy); } } else { - // ## TODO: this case needs to be plain code polygonal paths - QPainterPath path; - if (m_element_types.isEmpty()) { - if (!m_elements.isEmpty()) - path.moveTo(m_elements.at(0)); - for (int i=1; i<m_elements.size(); ++i) - path.lineTo(m_elements.at(i)); - } else { - for (int i=0; i<m_elements.size(); ++i) { - switch (m_element_types.at(i)) { - case QPainterPath::MoveToElement: - path.moveTo(m_elements.at(i)); - break; - case QPainterPath::LineToElement: - path.lineTo(m_elements.at(i)); - break; - case QPainterPath::CurveToElement: - path.cubicTo(m_elements.at(i), m_elements.at(i+1), m_elements.at(i+2)); - i += 2; - break; - default: - Q_ASSERT(false); - break; - } - } - } + const QVectorPath vp((qreal *)m_elements.data(), m_elements.size(), m_element_types.data()); + QPainterPath path = vp.convertToPainterPath(); 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; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 3d8e349..d9af3f6 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1675,34 +1675,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 @@ -1767,6 +1739,8 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) const QLineF *lines = reinterpret_cast<const QLineF *>(path.points()); for (int i = 0; i < lineCount; ++i) { + if (path.shape() == QVectorPath::LinesHint) + dashOffset = s->lastPen.dashOffset(); if (lines[i].p1() == lines[i].p2()) { if (s->lastPen.capStyle() != Qt::FlatCap) { QPointF p = lines[i].p1(); @@ -1972,67 +1946,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(); @@ -3546,8 +3459,8 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) int m22 = int(s->matrix.m22()); int dx = qFloor(s->matrix.dx() + aliasedCoordinateDelta); int dy = qFloor(s->matrix.dy() + aliasedCoordinateDelta); - int dashOffset = int(s->lastPen.dashOffset()); for (int i=0; i<lineCount; ++i) { + int dashOffset = int(s->lastPen.dashOffset()); if (s->flags.int_xform) { const QLine &l = lines[i]; int x1 = l.x1() * m11 + dx; @@ -3646,8 +3559,8 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount) ? LineDrawNormal : LineDrawIncludeLastPixel; - int dashOffset = int(s->lastPen.dashOffset()); for (int i=0; i<lineCount; ++i) { + int dashOffset = int(s->lastPen.dashOffset()); QLineF line = (lines[i] * s->matrix).translated(aliasedCoordinateDelta, aliasedCoordinateDelta); const QRectF brect(QPointF(line.x1(), line.y1()), QPointF(line.x2(), line.y2())); 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 a71fe52..81dce4f 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()); @@ -384,7 +419,6 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) const qreal *lastPoint = points + (pointCount<<1); - d->activeStroker->begin(d->strokeHandler); d->strokeHandler->types.reset(); d->strokeHandler->pts.reset(); @@ -393,13 +427,13 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin) flags |= QVectorPath::CurvedShapeHint; - // ### Perspective Xforms are currently not supported... qreal txscale = 1; if (!(pen.isCosmetic() || (qt_scaleForTransform(state()->matrix, &txscale) && txscale != 1))) { // We include cosmetic pens in this case to avoid having to // change the current transform. Normal transformed, // non-cosmetic pens will be transformed as part of fill // later, so they are also covered here.. + d->activeStroker->begin(d->strokeHandler); if (types) { while (points < lastPoint) { switch (*types) { @@ -448,69 +482,75 @@ 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) { - while (points < lastPoint) { - switch (*types) { - case QPainterPath::MoveToElement: { - QPointF pt = (*(QPointF *) points) * state()->matrix; - d->activeStroker->moveTo(pt.x(), pt.y()); - points += 2; - ++types; - break; + if (state()->matrix.type() >= QTransform::TxProject) { + QPainterPath painterPath = state()->matrix.map(path.convertToPainterPath()); + d->activeStroker->strokePath(painterPath, d->strokeHandler, QTransform()); + } else { + d->activeStroker->begin(d->strokeHandler); + if (types) { + while (points < lastPoint) { + switch (*types) { + case QPainterPath::MoveToElement: { + QPointF pt = (*(QPointF *) points) * state()->matrix; + d->activeStroker->moveTo(pt.x(), pt.y()); + points += 2; + ++types; + break; + } + case QPainterPath::LineToElement: { + QPointF pt = (*(QPointF *) points) * state()->matrix; + d->activeStroker->lineTo(pt.x(), pt.y()); + points += 2; + ++types; + 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()); + points += 6; + types += 3; + flags |= QVectorPath::CurvedShapeHint; + break; + } + default: + break; + } } - case QPainterPath::LineToElement: { - QPointF pt = (*(QPointF *) points) * state()->matrix; + if (path.hasImplicitClose()) { + QPointF pt = * ((QPointF *) path.points()) * state()->matrix; d->activeStroker->lineTo(pt.x(), pt.y()); - points += 2; - ++types; - 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()); - points += 6; - types += 3; - flags |= QVectorPath::CurvedShapeHint; - break; - } - default: - break; - } - } - if (path.hasImplicitClose()) { - QPointF pt = * ((QPointF *) path.points()) * state()->matrix; - d->activeStroker->lineTo(pt.x(), pt.y()); - } - } else { - QPointF p = ((QPointF *)points)[0] * state()->matrix; - d->activeStroker->moveTo(p.x(), p.y()); - points += 2; - ++types; - while (points < lastPoint) { + } else { QPointF p = ((QPointF *)points)[0] * state()->matrix; - d->activeStroker->lineTo(p.x(), p.y()); + d->activeStroker->moveTo(p.x(), p.y()); points += 2; ++types; + while (points < lastPoint) { + QPointF p = ((QPointF *)points)[0] * state()->matrix; + d->activeStroker->lineTo(p.x(), p.y()); + points += 2; + ++types; + } + if (path.hasImplicitClose()) + d->activeStroker->lineTo(p.x(), p.y()); } - if (path.hasImplicitClose()) - d->activeStroker->lineTo(p.x(), p.y()); + d->activeStroker->end(); } - d->activeStroker->end(); d->stroker.setStrokeWidth(strokeWidth); 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 b5301d1..f9fd61e 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -3280,6 +3280,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/qregion.cpp b/src/gui/painting/qregion.cpp index 7289a6b..47d24b3 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -49,7 +49,7 @@ #include <qdebug.h> -#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE) +#if defined(Q_OS_UNIX) || defined(Q_WS_WIN) #include "qimage.h" #include "qbitmap.h" #include <stdlib.h> @@ -545,7 +545,7 @@ QRegion& QRegion::operator|=(const QRegion &r) \sa intersected() */ -#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE) +#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN) QRegion& QRegion::operator+=(const QRect &r) { return operator+=(QRegion(r)); @@ -561,16 +561,14 @@ QRegion& QRegion::operator+=(const QRect &r) \sa intersected() */ -#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE) QRegion& QRegion::operator&=(const QRegion &r) { return *this = *this & r; } -#endif /*! \overload \since 4.4 */ -#if defined (Q_OS_UNIX) || defined (Q_OS_WINCE) +#if defined (Q_OS_UNIX) || defined (Q_WS_WIN) QRegion& QRegion::operator&=(const QRect &r) { return *this = *this & r; @@ -591,10 +589,8 @@ QRegion& QRegion::operator&=(const QRect &r) \sa subtracted() */ -#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE) QRegion& QRegion::operator-=(const QRegion &r) { return *this = *this - r; } -#endif /*! Applies the xored() function to this region and \a r and @@ -731,7 +727,7 @@ bool QRegion::intersects(const QRect &rect) const return false; } -#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE) +#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN) /*! \overload \since 4.4 @@ -1086,7 +1082,7 @@ Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion) return result; } -#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE) +#if defined(Q_OS_UNIX) || defined(Q_WS_WIN) //#define QT_REGION_DEBUG /* @@ -1627,9 +1623,9 @@ QT_END_INCLUDE_NAMESPACE QT_BEGIN_INCLUDE_NAMESPACE # include "qregion_mac.cpp" QT_END_INCLUDE_NAMESPACE -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) QT_BEGIN_INCLUDE_NAMESPACE -# include "qregion_wince.cpp" +# include "qregion_win.cpp" QT_END_INCLUDE_NAMESPACE #elif defined(Q_WS_QWS) static QRegionPrivate qrp; @@ -3846,7 +3842,7 @@ QRegion::QRegion(const QRect &r, RegionType t) #if defined(Q_WS_X11) d->rgn = 0; d->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) d->rgn = 0; #endif if (t == Rectangle) { @@ -3868,7 +3864,7 @@ QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule) #if defined(Q_WS_X11) d->rgn = 0; d->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) d->rgn = 0; #endif d->qt_rgn = PolygonRegion(a.constData(), a.size(), @@ -3898,7 +3894,7 @@ QRegion::QRegion(const QBitmap &bm) #if defined(Q_WS_X11) d->rgn = 0; d->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) d->rgn = 0; #endif d->qt_rgn = qt_bitmapToRegion(bm); @@ -3913,7 +3909,7 @@ void QRegion::cleanUp(QRegion::QRegionData *x) XDestroyRegion(x->rgn); if (x->xrectangles) free(x->xrectangles); -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) if (x->rgn) qt_win_dispose_rgn(x->rgn); #endif @@ -3948,7 +3944,7 @@ QRegion QRegion::copy() const #if defined(Q_WS_X11) x->rgn = 0; x->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) x->rgn = 0; #endif if (d->qt_rgn) diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index 61a0623..8a56d54 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -59,7 +59,7 @@ QT_MODULE(Gui) template <class T> class QVector; class QVariant; -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) struct QRegionPrivate; #endif @@ -148,6 +148,7 @@ public: #elif defined(Q_WS_MAC) #if defined Q_WS_MAC32 RgnHandle toQDRgn() const; + RgnHandle toQDRgnForUpdate_sys() const; static QRegion fromQDRgn(RgnHandle shape); #endif #ifdef QT_MAC_USE_COCOA @@ -199,7 +200,7 @@ private: #elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) mutable RgnHandle unused; // Here for binary compatability reasons. ### Qt 5 remove. #endif -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) QRegionPrivate *qt_rgn; #endif }; diff --git a/src/gui/painting/qregion_mac.cpp b/src/gui/painting/qregion_mac.cpp index b57f234..9b0e99f 100644 --- a/src/gui/painting/qregion_mac.cpp +++ b/src/gui/painting/qregion_mac.cpp @@ -155,6 +155,44 @@ RgnHandle QRegion::toQDRgn() const } return rgnHandle; } + +/*! + \internal + Create's a RegionHandle, it's the caller's responsibility to release. + Returns 0 if the QRegion overflows. +*/ +RgnHandle QRegion::toQDRgnForUpdate_sys() const +{ + RgnHandle rgnHandle = qt_mac_get_rgn(); + if(d->qt_rgn && d->qt_rgn->numRects) { + RgnHandle tmp_rgn = qt_mac_get_rgn(); + int n = d->qt_rgn->numRects; + const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData(); + while (n--) { + + // detect overflow. Tested for use with HIViewSetNeedsDisplayInRegion + // in QWidgetPrivate::update_sys(). + enum { HIViewSetNeedsDisplayInRegionOverflow = 10000 }; // empirically determined conservative value + qDebug() << qt_r->x() << qt_r->y() << qt_r->right() << qt_r->bottom(); + if (qt_r->right() > HIViewSetNeedsDisplayInRegionOverflow || qt_r->bottom() > HIViewSetNeedsDisplayInRegionOverflow) { + qt_mac_dispose_rgn(tmp_rgn); + qt_mac_dispose_rgn(rgnHandle); + return 0; + } + + SetRectRgn(tmp_rgn, + qMax(SHRT_MIN, qt_r->x()), + qMax(SHRT_MIN, qt_r->y()), + qMin(SHRT_MAX, qt_r->right() + 1), + qMin(SHRT_MAX, qt_r->bottom() + 1)); + UnionRgn(rgnHandle, tmp_rgn, rgnHandle); + ++qt_r; + } + qt_mac_dispose_rgn(tmp_rgn); + } + return rgnHandle; +} + #endif #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) diff --git a/src/gui/painting/qregion_win.cpp b/src/gui/painting/qregion_win.cpp index 249b1a6..2d5e76b 100644 --- a/src/gui/painting/qregion_win.cpp +++ b/src/gui/painting/qregion_win.cpp @@ -39,27 +39,25 @@ ** ****************************************************************************/ +#include "qatomic.h" #include "qbitmap.h" #include "qbuffer.h" #include "qimage.h" #include "qpolygon.h" #include "qregion.h" #include "qt_windows.h" +#include "qpainterpath.h" +#include "qguifunctions_wince.h" QT_BEGIN_NAMESPACE +QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 }; -/* - In Windows versions before Windows Vista CreateRectRgn - when called in a multi-threaded - environment - might return an invalid handle. This function works around this limitation - by verifying the handle with a quick GetRegionData() call and re-creates the region - if necessary. -*/ HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom) { const int tries = 10; for (int i = 0; i < tries; ++i) { - HRGN region = 0; + HRGN region; switch (type) { case QRegion::Rectangle: region = CreateRectRgn(left, top, right, bottom); @@ -80,497 +78,73 @@ HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, return 0; } -#ifndef Q_OS_WINCE -HRGN qt_tryCreatePolygonRegion(const QPolygon &a, Qt::FillRule fillRule) -{ - const int tries = 10; - for (int i = 0; i < tries; ++i) { - HRGN region = CreatePolygonRgn(reinterpret_cast<const POINT*>(a.data()), a.size(), - fillRule == Qt::OddEvenFill ? ALTERNATE : WINDING); - if (region) { - if (GetRegionData(region, 0, 0)) - return region; - else - DeleteObject(region); - } - } - return 0; -} -#endif - -QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 }; - -QRegion::QRegion() - : d(&shared_empty) -{ - d->ref.ref(); -} - -#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp -QRegion::QRegion(const QRect &r, RegionType t) -{ - if (r.isEmpty()) { - d = &shared_empty; - d->ref.ref(); - } else { - d = new QRegionData; - d->ref = 1; - if (t == Rectangle) - d->rgn = qt_tryCreateRegion(t, r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); - else if (t == Ellipse) { - // need to add 1 to width/height for the ellipse to have correct boundingrect. - d->rgn = qt_tryCreateRegion(t, r.x(), r.y(), r.x() + r.width() + 1, r.y() + r.height() + 1); - } - } -} -#endif - -#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp -QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule) -{ - if (a.size() < 3) { - d = &shared_empty; - d->ref.ref(); - } else { - d = new QRegionData; - d->ref = 1; - d->rgn = qt_tryCreatePolygonRegion(a, fillRule); - } -} -#endif - -QRegion::QRegion(const QRegion &r) -{ - d = r.d; - d->ref.ref(); -} - -HRGN qt_win_bitmapToRegion(const QBitmap& bitmap) -{ - HRGN region=0; - QImage image = bitmap.toImage(); - const int MAXRECT = 256; - struct RData { - RGNDATAHEADER header; - RECT rect[MAXRECT]; - }; - RData data; - -#define FlushSpans \ - { \ - data.header.dwSize = sizeof(RGNDATAHEADER); \ - data.header.iType = RDH_RECTANGLES; \ - data.header.nCount = n; \ - data.header.nRgnSize = 0; \ - data.header.rcBound.bottom = y; \ - HRGN r = ExtCreateRegion(0, \ - sizeof(RGNDATAHEADER)+n*sizeof(RECT),(RGNDATA*)&data); \ - if (region) { \ - CombineRgn(region, region, r, RGN_OR); \ - DeleteObject(r); \ - } else { \ - region = r; \ - } \ - data.header.rcBound.top = y; \ - } - -#define AddSpan \ - { \ - data.rect[n].left=prev1; \ - data.rect[n].top=y; \ - data.rect[n].right=x-1+1; \ - data.rect[n].bottom=y+1; \ - n++; \ - if (n == MAXRECT) { \ - FlushSpans \ - n=0; \ - } \ - } - - data.header.rcBound.top = 0; - data.header.rcBound.left = 0; - data.header.rcBound.right = image.width()-1; - int n = 0; - - int zero = 0x00; - - int x, y; - for (y = 0; y < image.height(); ++y) { - uchar *line = image.scanLine(y); - int w = image.width(); - uchar all=zero; - int prev1 = -1; - for (x = 0; x < w;) { - uchar byte = line[x/8]; - if (x > w - 8 || byte != all) { - for (int b = 8; b > 0 && x < w; --b) { - if (!(byte & 0x01) == !all) { - // More of the same - } else { - // A change. - if (all != zero) { - AddSpan; - all = zero; - } else { - prev1 = x; - all = ~zero; - } - } - byte >>= 1; - ++x; - } - } else { - x += 8; - } - } - if (all != zero) { - AddSpan; - } - } - if (n) { - FlushSpans; - } - - if (!region) { - // Surely there is some better way. - region = qt_tryCreateRegion(QRegion::Rectangle, 0,0,1,1); - CombineRgn(region, region, region, RGN_XOR); - } - return region; -} - -#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp -QRegion::QRegion(const QBitmap &bm) -{ - if (bm.isNull()) { - d = &shared_empty; - d->ref.ref(); - } else { - d = new QRegionData; - d->ref = 1; - d->rgn = qt_win_bitmapToRegion(bm); - } -} -#endif - -void QRegion::cleanUp(QRegion::QRegionData *x) -{ - if (x->rgn) - DeleteObject(x->rgn); - delete x; -} - -QRegion::~QRegion() -{ - if (!d->ref.deref()) - cleanUp(d); -} - -QRegion &QRegion::operator=(const QRegion &r) -{ - r.d->ref.ref(); - if (!d->ref.deref()) - cleanUp(d); - d = r.d; - return *this; -} - - -QRegion QRegion::copy() const -{ - QRegion r; - QRegionData *x = new QRegionData; - x->ref = 1; - if (d->rgn) { - x->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 2, 2); - CombineRgn(x->rgn, d->rgn, 0, RGN_COPY); - } else { - x->rgn = 0; - } - if (!r.d->ref.deref()) - cleanUp(r.d); - r.d = x; - return r; -} - -bool QRegion::isEmpty() const -{ - return (d == &shared_empty || boundingRect().isEmpty()); -} - - -bool QRegion::contains(const QPoint &p) const -{ - return d->rgn ? PtInRegion(d->rgn, p.x(), p.y()) : false; -} - -bool QRegion::contains(const QRect &r) const -{ - if (!d->rgn) - return false; - RECT rect; - SetRect(&rect, r.left(), r.top(), r.right(), r.bottom()); - return RectInRegion(d->rgn, &rect); -} - - -void QRegion::translate(int dx, int dy) -{ - if (!d->rgn || (dx == 0 && dy == 0)) - return; - detach(); - OffsetRgn(d->rgn, dx, dy); -} - - -#define RGN_NOP -1 - -// Duplicates of those in qregion.cpp -#define QRGN_OR 6 -#define QRGN_AND 7 -#define QRGN_SUB 8 -#define QRGN_XOR 9 - -/* - Performs the actual OR, AND, SUB and XOR operation between regions. - Sets the resulting region handle to 0 to indicate an empty region. -*/ - -QRegion QRegion::winCombine(const QRegion &r, int op) const +QRegion qt_region_from_HRGN(HRGN rgn) { - int both=RGN_NOP, - left=RGN_NOP, - right=RGN_NOP; - switch (op) { - case QRGN_OR: - both = RGN_OR; - left = right = RGN_COPY; - break; - case QRGN_AND: - both = RGN_AND; - break; - case QRGN_SUB: - both = RGN_DIFF; - left = RGN_COPY; - break; - case QRGN_XOR: - both = RGN_XOR; - left = right = RGN_COPY; - break; - default: - qWarning("QRegion: Internal error in winCombine"); - } - - int allCombineRgnResults = NULLREGION; - QRegion result; - result.detach(); - result.d->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 0, 0); - if (d->rgn && r.d->rgn) - allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, r.d->rgn, both); - else if (d->rgn && left != RGN_NOP) - allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, d->rgn, left); - else if (r.d->rgn && right != RGN_NOP) - allCombineRgnResults = CombineRgn(result.d->rgn, r.d->rgn, r.d->rgn, right); - - if (allCombineRgnResults == NULLREGION || allCombineRgnResults == ERROR) - result = QRegion(); - - //##### do not delete this. A null pointer is different from an empty region in SelectClipRgn in qpainter_win! (M) -// if (allCombineRgnResults == NULLREGION) { -// if (result.data->rgn) -// DeleteObject(result.data->rgn); -// result.data->rgn = 0; // empty region -// } - return result; -} - -QRegion QRegion::unite(const QRegion &r) const -{ - if (!d->rgn) - return r; - if (!r.d->rgn) - return *this; - return winCombine(r, QRGN_OR); -} - -QRegion QRegion::unite(const QRect &r) const -{ - return unite(QRegion(r)); -} - -QRegion QRegion::intersect(const QRegion &r) const -{ - if (!r.d->rgn || !d->rgn) - return QRegion(); - return winCombine(r, QRGN_AND); -} - -QRegion QRegion::subtract(const QRegion &r) const -{ - if (!r.d->rgn || !d->rgn) - return *this; - return winCombine(r, QRGN_SUB); -} - -QRegion QRegion::eor(const QRegion &r) const -{ - if (!d->rgn) - return r; - if (!r.d->rgn) - return *this; - return winCombine(r, QRGN_XOR); -} - - -QRect QRegion::boundingRect() const -{ - if (!d->rgn) - return QRect(); - RECT r; - if (GetRgnBox(d->rgn, &r) == NULLREGION) - return QRect(); - else - return QRect(r.left, r.top, r.right - r.left, r.bottom - r.top); -} - -QVector<QRect> QRegion::rects() const -{ - if (d->rgn == 0) - return QVector<QRect>(); - - int numBytes = GetRegionData(d->rgn, 0, 0); + int numBytes = GetRegionData(rgn, 0, 0); if (numBytes == 0) - return QVector<QRect>(); + return QRegion(); char *buf = new char[numBytes]; if (buf == 0) - return QVector<QRect>(); + return QRegion(); RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf); - if (GetRegionData(d->rgn, numBytes, rd) == 0) { + if (GetRegionData(rgn, numBytes, rd) == 0) { delete [] buf; - return QVector<QRect>(); + return QRegion(); } - QVector<QRect> a(rd->rdh.nCount); + QRegion region; RECT *r = reinterpret_cast<RECT*>(rd->Buffer); - for (int i = 0; i < a.size(); ++i) { - a[i].setCoords(r->left, r->top, r->right - 1, r->bottom - 1); + for (int i = 0; i < rd->rdh.nCount; ++i) { + QRect rect; + rect.setCoords(r->left, r->top, r->right - 1, r->bottom - 1); ++r; + region |= rect; } delete [] buf; - return a; -} - -void QRegion::setRects(const QRect *rects, int num) -{ - *this = QRegion(); - if (!rects || num == 0 || (num == 1 && rects->isEmpty())) - return; - for (int i = 0; i < num; ++i) - *this |= rects[i]; -} - -int QRegion::numRects() const -{ - if (d->rgn == 0) - return 0; - - const int numBytes = GetRegionData(d->rgn, 0, 0); - if (numBytes == 0) - return 0; - - char *buf = new char[numBytes]; - if (buf == 0) - return 0; - - RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf); - if (GetRegionData(d->rgn, numBytes, rd) == 0) { - delete[] buf; - return 0; - } - - const int n = rd->rdh.nCount; - delete[] buf; - return n; + return region; } -bool QRegion::operator==(const QRegion &r) const +void qt_win_dispose_rgn(HRGN r) { - if (d == r.d) - return true; - if ((d->rgn == 0) ^ (r.d->rgn == 0)) // one is empty, not both - return false; - return d->rgn == 0 ? true // both empty - : EqualRgn(d->rgn, r.d->rgn); // both non-empty + if (r) + DeleteObject(r); } -QRegion& QRegion::operator+=(const QRegion &r) +static void qt_add_rect(HRGN &winRegion, QRect r) { - if (!r.d->rgn) - return *this; - - if (!d->rgn) { - *this = r; - return *this; + HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); + if (rgn) { + HRGN dest = CreateRectRgn(0,0,0,0); + int result = CombineRgn(dest, winRegion, rgn, RGN_OR); + if (result) { + DeleteObject(winRegion); + winRegion = dest; + } + DeleteObject(rgn); } - - detach(); - - int result; - result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_OR); - if (result == NULLREGION || result == ERROR) - *this = QRegion(); - - return *this; -} - -QRegion& QRegion::operator-=(const QRegion &r) -{ - if (!r.d->rgn || !d->rgn) - return *this; - - detach(); - - int result; - result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_DIFF); - if (result == NULLREGION || result == ERROR) - *this = QRegion(); - - return *this; } -QRegion& QRegion::operator&=(const QRegion &r) +void QRegion::ensureHandle() const { - if (!d->rgn) - return *this; - - if (!r.d->rgn) { - *this = QRegion(); - return *this; + if (d->rgn) + DeleteObject(d->rgn); + d->rgn = CreateRectRgn(0,0,0,0); + if (d->qt_rgn) { + if (d->qt_rgn->numRects == 1) { + QRect r = d->qt_rgn->extents; + qt_add_rect(d->rgn, r); + return; + } + for (int i = 0;i < d->qt_rgn->numRects;i++) { + QRect r = d->qt_rgn->rects.at(i); + qt_add_rect(d->rgn, r); + } } - - detach(); - - int result; - result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_AND); - if (result == NULLREGION || result == ERROR) - *this = QRegion(); - - return *this; -} - -bool qt_region_strictContains(const QRegion ®ion, const QRect &rect) -{ - Q_UNUSED(region); - Q_UNUSED(rect); - return false; } -void QRegion::ensureHandle() const -{ -} QT_END_NAMESPACE diff --git a/src/gui/painting/qregion_wince.cpp b/src/gui/painting/qregion_wince.cpp deleted file mode 100644 index 9c33123..0000000 --- a/src/gui/painting/qregion_wince.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** 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 version 1.0, 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. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qatomic.h" -#include "qbitmap.h" -#include "qbuffer.h" -#include "qimage.h" -#include "qpolygon.h" -#include "qregion.h" -#include "qt_windows.h" -#include "qpainterpath.h" -#include "qguifunctions_wince.h" - -QT_BEGIN_NAMESPACE - -QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 }; - -HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom) -{ - const int tries = 10; - for (int i = 0; i < tries; ++i) { - HRGN region; - switch (type) { - case QRegion::Rectangle: - region = CreateRectRgn(left, top, right, bottom); - break; - case QRegion::Ellipse: -#ifndef Q_OS_WINCE - region = CreateEllipticRgn(left, top, right, bottom); -#endif - break; - } - if (region) { - if (GetRegionData(region, 0, 0)) - return region; - else - DeleteObject(region); - } - } - return 0; -} - -void qt_win_dispose_rgn(HRGN r) -{ - if (r) - DeleteObject(r); -} - -static void qt_add_rect(HRGN &winRegion, QRect r) -{ - HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); - if (rgn) { - HRGN dest = CreateRectRgn(0,0,0,0); - int result = CombineRgn(dest, winRegion, rgn, RGN_OR); - if (result) { - DeleteObject(winRegion); - winRegion = dest; - } - } -} - -void QRegion::ensureHandle() const -{ - if (d->rgn) - DeleteObject(d->rgn); - d->rgn = CreateRectRgn(0,0,0,0); - if (d->qt_rgn) { - if (d->qt_rgn->numRects == 1) { - QRect r = d->qt_rgn->extents; - qt_add_rect(d->rgn, r); - return; - } - for (int i = 0;i < d->qt_rgn->numRects;i++) { - QRect r = d->qt_rgn->rects.at(i); - qt_add_rect(d->rgn, r); - } - } -} - - -QT_END_NAMESPACE diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index 6968f4e..a34c354 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -60,6 +60,10 @@ #include <private/qfontengineglyphcache_p.h> +#if defined(Q_OS_VXWORKS) && defined(m_type) +# undef m_type +#endif + struct glyph_metrics_t; typedef unsigned int glyph_t; diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index a322fe4..0a64e4e 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -48,6 +48,8 @@ #include "qvariant.h" #include <qmath.h> +#include <private/qbezier_p.h> + QT_BEGIN_NAMESPACE #define Q_NEAR_CLIP 0.000001 @@ -1492,27 +1494,12 @@ static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transfor static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo) { - const QHomogeneousCoordinate ha = mapHomogeneous(transform, a); - const QHomogeneousCoordinate hb = mapHomogeneous(transform, b); - const QHomogeneousCoordinate hc = mapHomogeneous(transform, c); - const QHomogeneousCoordinate hd = mapHomogeneous(transform, d); - - if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP && hc.w < Q_NEAR_CLIP && hd.w < Q_NEAR_CLIP) - return false; + // Convert projective xformed curves to line + // segments so they can be transformed more accurately + QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(); - if (ha.w >= Q_NEAR_CLIP && hb.w >= Q_NEAR_CLIP && hc.w >= Q_NEAR_CLIP && hd.w >= Q_NEAR_CLIP) { - if (needsMoveTo) - path.moveTo(ha.toPoint()); - - path.cubicTo(hb.toPoint(), hc.toPoint(), hd.toPoint()); - return true; - } - - if (lineTo_clipped(path, transform, a, b, needsMoveTo)) - needsMoveTo = false; - if (lineTo_clipped(path, transform, b, c, needsMoveTo)) - needsMoveTo = false; - if (lineTo_clipped(path, transform, c, d, needsMoveTo)) + for (int i = 0; i < segment.size() - 1; ++i) + if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo)) needsMoveTo = false; return !needsMoveTo; @@ -1793,6 +1780,14 @@ void QTransform::setMatrix(qreal m11, qreal m12, qreal m13, m_dirty = TxProject; } +static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform) +{ + const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right()); + const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom()); + + return wx + wy + transform.m33() < Q_NEAR_CLIP; +} + QRect QTransform::mapRect(const QRect &rect) const { TransformationType t = inline_type(); @@ -1813,7 +1808,7 @@ QRect QTransform::mapRect(const QRect &rect) const y -= h; } return QRect(x, y, w, h); - } else { + } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) { // see mapToPolygon for explanations of the algorithm. qreal x = 0, y = 0; MAP(rect.left(), rect.top(), x, y); @@ -1837,6 +1832,10 @@ QRect QTransform::mapRect(const QRect &rect) const xmax = qMax(xmax, x); ymax = qMax(ymax, y); return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin)); + } else { + QPainterPath path; + path.addRect(rect); + return map(path).boundingRect().toRect(); } } @@ -1879,7 +1878,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const y -= h; } return QRectF(x, y, w, h); - } else { + } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) { qreal x = 0, y = 0; MAP(rect.x(), rect.y(), x, y); qreal xmin = x; @@ -1902,6 +1901,10 @@ QRectF QTransform::mapRect(const QRectF &rect) const xmax = qMax(xmax, x); ymax = qMax(ymax, y); return QRectF(xmin, ymin, xmax-xmin, ymax - ymin); + } else { + QPainterPath path; + path.addRect(rect); + return map(path).boundingRect(); } } diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index 291d35c..69d4de2 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -50,6 +50,10 @@ #include <QtCore/qpoint.h> #include <QtCore/qrect.h> +#if defined(Q_OS_VXWORKS) && defined(m_type) +# undef m_type +#endif + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h index e3cb333..df49500 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) diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index 63b39b2..863237b 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -116,7 +116,7 @@ QPaintDevice *QRasterWindowSurface::paintDevice() void QRasterWindowSurface::beginPaint(const QRegion &rgn) { #if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE)) - if (!qt_widget_private(window())->isOpaque) { + if (!qt_widget_private(window())->isOpaque && window()->testAttribute(Qt::WA_TranslucentBackground)) { #if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) if (d_ptr->image->image.format() != QImage::Format_ARGB32_Premultiplied) prepareBuffer(QImage::Format_ARGB32_Premultiplied, window()); @@ -147,7 +147,7 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi QRect br = rgn.boundingRect(); #ifndef Q_WS_WINCE - if (!qt_widget_private(window())->isOpaque) { + if (!qt_widget_private(window())->isOpaque && window()->testAttribute(Qt::WA_TranslucentBackground)) { QRect r = window()->frameGeometry(); QPoint frameOffset = qt_widget_private(window())->frameStrut().topLeft(); QRect dirtyRect = br.translated(offset + frameOffset); diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp index d8b0d9e..95f6ce3 100644 --- a/src/gui/painting/qwindowsurface_x11.cpp +++ b/src/gui/painting/qwindowsurface_x11.cpp @@ -154,7 +154,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect) QX11PixmapData *oldData = static_cast<QX11PixmapData *>(d_ptr->device.pixmapData()); Q_ASSERT(oldData); - if (!oldData->uninit && hasStaticContents()) { + if (!(oldData->flags & QX11PixmapData::Uninitialized) && hasStaticContents()) { // Copy the content of the old pixmap into the new one. QX11PixmapData *newData = new QX11PixmapData(QPixmapData::PixmapType); newData->resize(size.width(), size.height()); @@ -175,7 +175,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect) dx, dy, qMin(boundingRect.width(), size.width()), qMin(boundingRect.height(), size.height()), dx, dy); XFreeGC(X11->display, tmpGc); - newData->uninit = false; + newData->flags &= ~QX11PixmapData::Uninitialized; d_ptr->device = QPixmap(newData); } else { |