summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
authorKent Hansen <khansen@trolltech.com>2009-08-05 14:10:47 (GMT)
committerKent Hansen <khansen@trolltech.com>2009-08-05 14:10:47 (GMT)
commit1d7d5436eea09a232187836e59d2a937a752dee4 (patch)
tree6bd9ae61abb1467aceddc5a828fc2e65d93b2534 /src/gui/painting
parent791bddfcd5cc7540219835ef5d91486acd833c4b (diff)
parentfb8bb148affec842e8fa1a70616c64c7d3066ee8 (diff)
downloadQt-1d7d5436eea09a232187836e59d2a937a752dee4.zip
Qt-1d7d5436eea09a232187836e59d2a937a752dee4.tar.gz
Qt-1d7d5436eea09a232187836e59d2a937a752dee4.tar.bz2
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt into qtscript-jsc-backend
Conflicts: src/script/qscriptextqobject.cpp
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/painting.pri8
-rw-r--r--src/gui/painting/qblendfunctions.cpp8
-rw-r--r--src/gui/painting/qdatabuffer_p.h17
-rw-r--r--src/gui/painting/qdrawhelper.cpp72
-rw-r--r--src/gui/painting/qoutlinemapper.cpp69
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp6
-rw-r--r--src/gui/painting/qpaintengineex.cpp106
-rw-r--r--src/gui/painting/qpainter.cpp2
-rw-r--r--src/gui/painting/qregion.cpp28
-rw-r--r--src/gui/painting/qregion.h5
-rw-r--r--src/gui/painting/qregion_mac.cpp37
-rw-r--r--src/gui/painting/qregion_win.cpp512
-rw-r--r--src/gui/painting/qregion_wince.cpp119
-rw-r--r--src/gui/painting/qtransform.cpp48
-rw-r--r--src/gui/painting/qwindowsurface_raster.cpp4
-rw-r--r--src/gui/painting/qwindowsurface_x11.cpp4
16 files changed, 246 insertions, 799 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 34d1779..d226be2 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -100,8 +100,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
}
@@ -126,10 +126,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/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/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h
index b568f43..275ec13 100644
--- a/src/gui/painting/qdatabuffer_p.h
+++ b/src/gui/painting/qdatabuffer_p.h
@@ -114,23 +114,6 @@ 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/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 979390a..b6603e4 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -4794,30 +4794,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/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index 9c073f2..1287672 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qoutlinemapper_p.h"
-#include "qbezier_p.h"
#include "qmath.h"
@@ -199,70 +198,30 @@ void QOutlineMapper::endOutline()
m_m22 * e.y() + m_m12 * e.x() + m_dy);
}
} else {
- // ## TODO: this case needs to be plain code polygonal paths
- 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())
- m_elements_dev << m_elements.at(0) * matrix;
- for (int i=1; i<m_elements.size(); ++i)
- m_elements_dev << m_elements.at(i) * matrix;
-
- } else {
- for (int i=0, t=0; i<m_elements.size(); ++i) {
- switch (m_element_types.at(t)) {
- case QPainterPath::MoveToElement:
- m_elements_dev << m_elements.at(i) * matrix;
- ++t;
- break;
- case QPainterPath::LineToElement:
- m_elements_dev << m_elements.at(i) * matrix;
- ++t;
- break;
- 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;
- default:
- Q_ASSERT(false);
- break;
- }
- }
- element_count = m_elements_dev.size();
- }
+ 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);
+ if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL))
+ path.setFillRule(Qt::WindingFill);
+ 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 < element_count; ++i)
+ for (int i = 0; i < m_elements.size(); ++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 69e490a..74456dd 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1736,6 +1736,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();
@@ -3454,8 +3456,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;
@@ -3554,8 +3556,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/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 8ec881e..ed9b858 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -421,7 +421,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();
@@ -430,13 +429,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) {
@@ -491,79 +490,64 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
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: {
- 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: {
- // 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 {
+ 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;
}
- 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());
}
- }
- 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(),
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 9c7a7fa..8192fb7 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -1672,7 +1672,7 @@ bool QPainter::begin(QPaintDevice *pd)
if (!d->engine) {
qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
- return true;
+ return false;
}
// Slip a painter state into the engine before we do any other operations
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 762e9e0..d59f3ff 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 &region)
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;
@@ -3829,7 +3825,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) {
@@ -3851,7 +3847,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(),
@@ -3881,7 +3877,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);
@@ -3896,7 +3892,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
@@ -3932,7 +3928,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 bfedcb1..84024ce 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)
+#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN)
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)
+#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN)
QRegionPrivate *qt_rgn;
#endif
};
diff --git a/src/gui/painting/qregion_mac.cpp b/src/gui/painting/qregion_mac.cpp
index b57f234..6fe7805 100644
--- a/src/gui/painting/qregion_mac.cpp
+++ b/src/gui/painting/qregion_mac.cpp
@@ -155,6 +155,43 @@ 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
+ 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..8708461 100644
--- a/src/gui/painting/qregion_win.cpp
+++ b/src/gui/painting/qregion_win.cpp
@@ -39,22 +39,20 @@
**
****************************************************************************/
+#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;
@@ -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 (uint 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 &region, 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/qtransform.cpp b/src/gui/painting/qtransform.cpp
index a322fe4..a13b494 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;
@@ -1554,6 +1541,7 @@ static QPainterPath mapProjective(const QTransform &transform, const QPainterPat
if (path.elementCount() > 0 && lastMoveTo != last)
lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo, false);
+ result.setFillRule(path.fillRule());
return result;
}
@@ -1793,6 +1781,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 +1809,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 +1833,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 +1879,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 +1902,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/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp
index 22433dd..eddbfd2 100644
--- a/src/gui/painting/qwindowsurface_raster.cpp
+++ b/src/gui/painting/qwindowsurface_raster.cpp
@@ -118,7 +118,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());
@@ -149,7 +149,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 {