summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/embedded/qscreen_qws.cpp5
-rw-r--r--src/gui/painting/qdrawhelper_p.h3
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp227
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h1
4 files changed, 138 insertions, 98 deletions
diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp
index f3f54d9..91121e7 100644
--- a/src/gui/embedded/qscreen_qws.cpp
+++ b/src/gui/embedded/qscreen_qws.cpp
@@ -49,6 +49,7 @@
#include "qpixmap.h"
#include "qvarlengtharray.h"
#include "qwsdisplay_qws.h"
+#include "qpainter.h"
#include <private/qdrawhelper_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qpixmap_raster_p.h>
@@ -2710,7 +2711,7 @@ void QScreen::compose(int level, const QRegion &exposed, QRegion &blend,
default:
break;
}
- spanData.setup(qwsServer->backgroundBrush(), 256);
+ spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_SourceOver);
spanData.dx = off.x();
spanData.dy = off.y();
} else if (!surface->isBuffered()) {
@@ -2775,7 +2776,7 @@ void QScreen::paintBackground(const QRegion &r)
rb.prepare(&img);
QSpanData spanData;
spanData.init(&rb, 0);
- spanData.setup(bg, 256);
+ spanData.setup(bg, 256, QPainter::CompositionMode_Source);
spanData.dx = off.x();
spanData.dy = off.y();
Q_ASSERT(spanData.blend);
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index de97683..019402a 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -110,6 +110,7 @@ struct QSpanData;
class QGradient;
class QRasterBuffer;
class QClipData;
+class QRasterPaintEngineState;
typedef QT_FT_SpanFunc ProcessSpans;
typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer,
@@ -293,7 +294,7 @@ struct QSpanData
};
void init(QRasterBuffer *rb, const QRasterPaintEngine *pe);
- void setup(const QBrush &brush, int alpha);
+ void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode);
void setupMatrix(const QTransform &matrix, int bilinear);
void initTexture(const QImage *image, int alpha, QTextureData::Type = QTextureData::Plain, const QRect &sourceRect = QRect());
void adjustSpanMethods();
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index c986e99..0e8f50a 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -139,7 +139,6 @@ extern bool qt_cleartype_enabled;
* Span functions
*/
static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData);
-static void qt_span_fill_clipRegion(int count, const QSpan *spans, void *userData);
static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData);
static void qt_span_clip(int count, const QSpan *spans, void *userData);
static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result);
@@ -363,7 +362,8 @@ void QRasterPaintEngine::init()
d->basicStroker.setCubicToHook(qt_ft_outline_cubic_to);
d->dashStroker = 0;
- d->baseClip = 0;
+ d->baseClip = new QClipData(d->device->height());
+ d->baseClip->setClipRect(QRect(0, 0, d->device->width(), d->device->height()));
d->image_filler.init(d->rasterBuffer, this);
d->image_filler.type = QSpanData::Texture;
@@ -447,6 +447,8 @@ QRasterPaintEngine::~QRasterPaintEngine()
delete d->outlineMapper;
delete d->rasterizer;
delete d->dashStroker;
+
+ delete d->baseClip;
}
/*!
@@ -483,12 +485,12 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
d->rasterizer->setClipRect(d->deviceRect);
s->penData.init(d->rasterBuffer, this);
- s->penData.setup(s->pen.brush(), s->intOpacity);
+ s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode);
s->stroker = &d->basicStroker;
d->basicStroker.setClipRect(d->deviceRect);
s->brushData.init(d->rasterBuffer, this);
- s->brushData.setup(s->brush, s->intOpacity);
+ s->brushData.setup(s->brush, s->intOpacity, s->composition_mode);
d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver;
@@ -542,11 +544,6 @@ bool QRasterPaintEngine::end()
}
#endif
- if (d->baseClip) {
- delete d->baseClip;
- d->baseClip = 0;
- }
-
return true;
}
@@ -773,7 +770,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen)
s->strokeFlags = 0;
s->penData.clip = d->clip();
- s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity);
+ s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s->composition_mode);
if (s->strokeFlags & QRasterPaintEngine::DirtyTransform
|| pen.brush().transform().type() >= QTransform::TxNone) {
@@ -873,7 +870,7 @@ void QRasterPaintEngine::updateBrush(const QBrush &brush)
QRasterPaintEngineState *s = state();
// must set clip prior to setup, as setup uses it...
s->brushData.clip = d->clip();
- s->brushData.setup(brush, s->intOpacity);
+ s->brushData.setup(brush, s->intOpacity, s->composition_mode);
if (s->fillFlags & DirtyTransform
|| brush.transform().type() >= QTransform::TxNone)
d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix());
@@ -1028,6 +1025,10 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
{
if (alpha == 0 || !clip.isValid())
return;
+
+ if (alpha ==0)
+ return;
+
Q_ASSERT(img.depth() >= 8);
int srcBPL = img.bytesPerLine();
@@ -1096,11 +1097,10 @@ void QRasterPaintEnginePrivate::systemStateChanged()
if (!systemClip.isEmpty()) {
QRegion clippedDeviceRgn = systemClip & clipRect;
deviceRect = clippedDeviceRgn.boundingRect();
- delete baseClip;
- baseClip = new QClipData(device->height());
baseClip->setClipRegion(clippedDeviceRgn);
} else {
deviceRect = clipRect;
+ baseClip->setClipRect(deviceRect);
}
#ifdef QT_DEBUG_DRAW
qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRect << systemClip;
@@ -1172,6 +1172,25 @@ static void checkClipRatios(QRasterPaintEnginePrivate *d)
}
#endif
+static void qrasterpaintengine_state_setNoClip(QRasterPaintEngineState *s)
+{
+ if (s->flags.has_clip_ownership)
+ delete s->clip;
+ s->clip = 0;
+ s->flags.has_clip_ownership = false;
+}
+
+static void qrasterpaintengine_dirty_clip(QRasterPaintEnginePrivate *d, QRasterPaintEngineState *s)
+{
+ s->fillFlags |= QPaintEngine::DirtyClipPath;
+ s->strokeFlags |= QPaintEngine::DirtyClipPath;
+ s->pixmapFlags |= QPaintEngine::DirtyClipPath;
+
+ d->solid_color_filler.clip = d->clip();
+ d->solid_color_filler.adjustSpanMethods();
+}
+
+
/*!
\internal
*/
@@ -1220,10 +1239,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
}
if (op == Qt::NoClip) {
- if (s->flags.has_clip_ownership)
- delete s->clip;
- s->clip = 0;
- s->flags.has_clip_ownership = false;
+ qrasterpaintengine_state_setNoClip(s);
} else {
QClipData *base = d->baseClip;
@@ -1265,17 +1281,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
s->clip = newClip;
s->flags.has_clip_ownership = true;
}
-
- s->fillFlags |= DirtyClipPath;
- s->strokeFlags |= DirtyClipPath;
- s->pixmapFlags |= DirtyClipPath;
-
- d->solid_color_filler.clip = d->clip();
- d->solid_color_filler.adjustSpanMethods();
-
-#ifdef QT_CLIPPING_RATIOS
- checkClipRatios(d);
-#endif
+ qrasterpaintengine_dirty_clip(d, s);
}
@@ -1293,10 +1299,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
QRasterPaintEngineState *s = state();
if (op == Qt::NoClip) {
- if (s->flags.has_clip_ownership)
- delete s->clip;
- s->clip = d->baseClip;
- s->flags.has_clip_ownership = false;
+ qrasterpaintengine_state_setNoClip(s);
} else if (op == Qt::UniteClip || s->matrix.type() > QTransform::TxScale) {
QPaintEngineEx::clip(rect, op);
@@ -1340,37 +1343,63 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
return;
}
}
-
- s->brushData.clip = d->clip();
- s->penData.clip = d->clip();
-
- s->fillFlags |= DirtyClipPath;
- s->strokeFlags |= DirtyClipPath;
- s->pixmapFlags |= DirtyClipPath;
-
- d->solid_color_filler.clip = d->clip();
- d->solid_color_filler.adjustSpanMethods();
-
-
-#ifdef QT_CLIPPING_RATIOS
- checkClipRatios(d);
-#endif
+ qrasterpaintengine_dirty_clip(d, s);
}
+
/*!
\internal
*/
void QRasterPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
{
- QPaintEngineEx::clip(region, op);
-}
+#ifdef QT_DEBUG_DRAW
+ qDebug() << "QRasterPaintEngine::clip(): " << region << op;
+#endif
-/*!
- \internal
-*/
-void QRasterPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
-{
- QPaintEngineEx::clip(path, op);
+ Q_D(QRasterPaintEngine);
+
+ if (region.numRects() == 1) {
+ clip(region.boundingRect(), op);
+ return;
+ }
+
+ QRasterPaintEngineState *s = state();
+ const QClipData *clip = d->clip();
+ const QClipData *baseClip = d->baseClip;
+
+ if (op == Qt::NoClip) {
+ qrasterpaintengine_state_setNoClip(s);
+ } else if (s->matrix.type() > QTransform::TxScale
+ || op == Qt::UniteClip
+ || (op == Qt::IntersectClip && !clip->hasRectClip && !clip->hasRegionClip)
+ || (op == Qt::ReplaceClip && !baseClip->hasRectClip && !baseClip->hasRegionClip)) {
+ QPaintEngineEx::clip(region, op);
+ } else {
+ const QClipData *curClip;
+ QClipData *newClip;
+
+ if (op == Qt::IntersectClip)
+ curClip = clip;
+ else
+ curClip = baseClip;
+
+ if (s->flags.has_clip_ownership) {
+ newClip = s->clip;
+ Q_ASSERT(newClip);
+ } else {
+ newClip = new QClipData(d->rasterBuffer->height());
+ s->clip = newClip;
+ s->flags.has_clip_ownership = true;
+ }
+
+ QRegion r = s->matrix.map(region);
+ if (curClip->hasRectClip)
+ newClip->setClipRegion(r & curClip->clipRect);
+ else if (curClip->hasRegionClip)
+ newClip->setClipRegion(r & clip->clipRegion);
+
+ qrasterpaintengine_dirty_clip(d, s);
+ }
}
/*!
@@ -1412,7 +1441,7 @@ static void fillRect_normalized(const QRect &r, QSpanData *data,
{
int x1, x2, y1, y2;
- bool rectClipped = false;
+ bool rectClipped = true;
if (data->clip) {
x1 = qMax(r.x(), data->clip->xmin);
@@ -1742,12 +1771,17 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
static inline QRect toNormalizedFillRect(const QRectF &rect)
{
- const int x1 = qRound(rect.x() + aliasedCoordinateDelta);
- const int y1 = qRound(rect.y() + aliasedCoordinateDelta);
- const int x2 = qRound(rect.right() + aliasedCoordinateDelta);
- const int y2 = qRound(rect.bottom() + aliasedCoordinateDelta);
+ int x1 = int(rect.x() + aliasedCoordinateDelta);
+ int y1 = int(rect.y() + aliasedCoordinateDelta);
+ int x2 = int(rect.right() + aliasedCoordinateDelta);
+ int y2 = int(rect.bottom() + aliasedCoordinateDelta);
- return QRect(x1, y1, x2 - x1, y2 - y1).normalized();
+ if (x2 < x1)
+ qSwap(x1, x2);
+ if (y2 < y1)
+ qSwap(y1, y2);
+
+ return QRect(x1, y1, x2 - x1, y2 - y1);
}
/*!
@@ -1907,9 +1941,12 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color)
QRasterPaintEngineState *s = state();
d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity));
+ if ((d->solid_color_filler.solid.color & 0xff000000) == 0
+ && s->composition_mode == QPainter::CompositionMode_SourceOver) {
+ return;
+ }
d->solid_color_filler.clip = d->clip();
d->solid_color_filler.adjustSpanMethods();
-
fillRect(r, &d->solid_color_filler);
}
@@ -3076,7 +3113,7 @@ bool QRasterPaintEnginePrivate::isUnclipped_normalized(const QRect &r) const
if (cl->clipRect == deviceRect)
return true;
- if (cl->hasRegionClip) {
+ if (cl->hasRectClip) {
// inline contains() for performance (we know the rects are normalized)
const QRect &r1 = cl->clipRect;
return (r.left() >= r1.left() && r.right() <= r1.right()
@@ -4307,6 +4344,7 @@ void QClipData::initialize()
m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan));
+ allocated = clipSpanHeight;
if (hasRectClip) {
int y = 0;
@@ -4351,6 +4389,7 @@ void QClipData::initialize()
int y = 0;
int firstInBand = 0;
+ count = 0;
while (firstInBand < numRects) {
const int currMinY = rects.at(firstInBand).y();
const int currMaxY = currMinY + rects.at(firstInBand).height();
@@ -4411,20 +4450,39 @@ void QClipData::fixup()
ymax = m_spans[count-1].y + 1;
xmin = INT_MAX;
xmax = 0;
+
+ bool isRect = true;
+ int left = m_spans[0].x;
+ int right = m_spans[0].x + m_spans[0].len;
+
for (int i = 0; i < count; ++i) {
-// qDebug() << " " << spans[i].x << spans[i].y << spans[i].len << spans[i].coverage;
if (m_spans[i].y != y) {
+ if (m_spans[i].y != y + 1 && y != -1) {
+ isRect = false;
+ }
y = m_spans[i].y;
m_clipLines[y].spans = m_spans+i;
m_clipLines[y].count = 0;
// qDebug() << " new line: y=" << y;
}
++m_clipLines[y].count;
+ int sl = (int) m_spans[i].x;
+ int sr = sl + m_spans[i].len;
+
xmin = qMin(xmin, (int)m_spans[i].x);
xmax = qMax(xmax, (int)m_spans[i].x + m_spans[i].len);
+
+ if (sl != left || sr != right)
+ isRect = false;
}
++xmax;
-// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d", xmin, xmax, ymin, ymax);
+// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d %s", xmin, xmax, ymin, ymax, isRect ? "rectangular" : "");
+
+ if (isRect) {
+ hasRectClip = true;
+ clipRect.setRect(xmin, ymin, xmax - xmin, ymax - ymin);
+ }
+
}
/*
@@ -4437,6 +4495,7 @@ void QClipData::setClipRect(const QRect &rect)
// qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect;
hasRectClip = true;
+ hasRegionClip = false;
clipRect = rect;
xmin = rect.x();
@@ -4445,7 +4504,7 @@ void QClipData::setClipRect(const QRect &rect)
ymax = qMin(rect.y() + rect.height(), clipSpanHeight);
if (m_spans) {
- delete m_spans;
+ free(m_spans);
m_spans = 0;
}
@@ -4463,6 +4522,7 @@ void QClipData::setClipRegion(const QRegion &region)
}
hasRegionClip = true;
+ hasRectClip = false;
clipRegion = region;
{ // set bounding rect
@@ -4474,7 +4534,7 @@ void QClipData::setClipRegion(const QRegion &region)
}
if (m_spans) {
- delete m_spans;
+ free(m_spans);
m_spans = 0;
}
@@ -4722,29 +4782,6 @@ static void qt_span_fill_clipRect(int count, const QSpan *spans,
fillData->unclipped_blend(count, spans, fillData);
}
-static void qt_span_fill_clipRegion(int count, const QSpan *spans,
- void *userData)
-{
- QSpanData *fillData = reinterpret_cast<QSpanData *>(userData);
- Q_ASSERT(fillData->blend && fillData->unclipped_blend);
-
- Q_ASSERT(fillData->clip);
- Q_ASSERT(!fillData->clip->clipRegion.isEmpty());
-
- const int NSPANS = 256;
- QSpan cspans[NSPANS];
- int currentClip = 0;
- while (currentClip < count) {
- const int unclipped = qt_intersect_spans(const_cast<QSpan*>(spans),
- count, &currentClip,
- &cspans[0], NSPANS,
- fillData->clip->clipRegion);
- if (unclipped > 0)
- fillData->unclipped_blend(unclipped, cspans, fillData);
- }
-
-}
-
static void qt_span_clip(int count, const QSpan *spans, void *userData)
{
ClipData *clipData = reinterpret_cast<ClipData *>(userData);
@@ -5017,7 +5054,7 @@ void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe)
extern QImage qt_imageForBrush(int brushStyle, bool invert);
-void QSpanData::setup(const QBrush &brush, int alpha)
+void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode)
{
Qt::BrushStyle brushStyle = qbrush_style(brush);
switch (brushStyle) {
@@ -5025,6 +5062,10 @@ void QSpanData::setup(const QBrush &brush, int alpha)
type = Solid;
QColor c = qbrush_color(brush);
solid.color = PREMUL(ARGB_COMBINE_ALPHA(c.rgba(), alpha));
+ if ((solid.color & 0xff000000) == 0
+ && compositionMode == QPainter::CompositionMode_SourceOver) {
+ type = None;
+ }
break;
}
@@ -5165,8 +5206,6 @@ void QSpanData::adjustSpanMethods()
blend = unclipped_blend;
} else if (clip->hasRectClip) {
blend = clip->clipRect.isEmpty() ? 0 : qt_span_fill_clipRect;
- } else if (clip->hasRegionClip) {
- blend = clip->clipRegion.isEmpty() ? 0 : qt_span_fill_clipRegion;
} else {
blend = qt_span_fill_clipped;
}
@@ -6147,7 +6186,7 @@ void dumpClip(int width, int height, QClipData *clip)
int y1 = 0;
for (int i = 0; i < clip->count; ++i) {
- QSpan *span = clip->spans + i;
+ QSpan *span = clip->spans() + i;
for (int j = 0; j < span->len; ++j)
clipImg.setPixel(span->x + j, span->y, 0xffffff00);
x0 = qMin(x0, int(span->x));
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 26a2b3f..1f3f006 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -202,7 +202,6 @@ public:
void clip(const QVectorPath &path, Qt::ClipOperation op);
void clip(const QRect &rect, Qt::ClipOperation op);
void clip(const QRegion &region, Qt::ClipOperation op);
- void clip(const QPainterPath &path, Qt::ClipOperation op);
enum ClipType {
RectClip,