Painting: fix overriding and combining different clip types

In a recent improvement (6de36918c0) the
last set clip region or path was stored in separate variables, in
order to be set again if the aliasing mode changed. That solution was
too simplistic, as it would break down as soon as more than one clip
area was set, with the latter either replacing or intersecting the
first. It was also unnecessary to introduce new storing of clip areas
and transforms, as those are already recorded in the clipInfo stack in
the painter state. This patch hence reverts much of that implementation.

However the basic idea of setting the clip area again after AA change
is good, so that part is kept, implementated instead by calling a
pre-existing function to replay the clipInfo stack.

One of the baseline test cases is extended to excercise the
combination of clip areas. As a driveby, support for setClipRectF is
added to the painting baseline test scripts, and the build of the
manual lance tool is fixed.

Fixes: QTBUG-101474
Pick-to: 6.3 6.2
Change-Id: Ide8b70d8cbf138deb06cbb84f69e62f7405886e6
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
Eirik Aavitsland 2022-03-11 14:15:44 +01:00
parent 1822550529
commit f46db29d8c
7 changed files with 323 additions and 32 deletions

View File

@ -1223,7 +1223,6 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
ensureOutlineMapper();
d->rasterize(d->outlineMapper->convertPath(path), qt_span_clip, &clipData, nullptr);
newClip->clipTransform = s->matrix;
newClip->fixup();
if (s->flags.has_clip_ownership)
@ -1308,7 +1307,6 @@ bool QRasterPaintEngine::setClipRectInDeviceCoords(const QRect &r, Qt::ClipOpera
return false;
}
s->clip->clipTransform = s->matrix;
qrasterpaintengine_dirty_clip(d, s);
return true;
}
@ -1364,7 +1362,6 @@ void QRasterPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
else if (curClip->hasRegionClip)
newClip->setClipRegion(r & curClip->clipRegion);
newClip->clipTransform = s->matrix;
qrasterpaintengine_dirty_clip(d, s);
}
}
@ -3704,27 +3701,8 @@ void QRasterPaintEnginePrivate::updateClipping()
if (!s->clipEnabled)
return;
bool noClipPath = s->clipPath.isEmpty();
bool noClipRegion = s->clipRegion.isEmpty();
if (noClipPath && noClipRegion)
return;
if (!s->clip)
return;
const QTransform stateTransform = s->matrix;
s->matrix = s->clip->clipTransform;
qrasterpaintengine_state_setNoClip(s);
if (noClipRegion) {
q->clip(qtVectorPathForPath(s->clipPath), s->clipOperation);
} else {
q->clip(s->clipRegion, s->clipOperation);
}
s->matrix = stateTransform;
replayClipOperations();
}
void QRasterPaintEnginePrivate::recalculateFastImages()

View File

@ -374,7 +374,6 @@ public:
QRect clipRect;
QRegion clipRegion;
QTransform clipTransform;
uint enabled : 1;
uint hasRectClip : 1;

View File

@ -2848,7 +2848,6 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
d->state->clipInfo.clear();
d->state->clipInfo.append(QPainterClipInfo(r, op, d->state->matrix));
d->state->clipOperation = op;
d->state->clipRegion = r;
return;
}
@ -3063,7 +3062,6 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
d->state->clipInfo.clear();
d->state->clipInfo.append(QPainterClipInfo(path, op, d->state->matrix));
d->state->clipOperation = op;
d->state->clipPath = path;
return;
}

View File

@ -1,7 +1,7 @@
# Version: 1
# CheckVsReference: 5%
save
translate 10 10
setPen NoPen
@ -56,4 +56,297 @@ setRenderHint Antialiasing
setRenderHint SmoothPixmapTransform
repeat_block clipping
restore
# Excercise combining different clips
translate 0 250
scale 0.9 0.9
setFont "times" 10 bold
region_addRect dummyRegion 1000 1000 10 10
region_addRect realRegion 20 10 60 30
path_addRect dummyPath 1000 1000 10 10
path_addRect realPath 20 10 60 30
begin_block paintstuff
fillRect 0 0 100 50 orange
drawText 0 5 "Should be clipped"
drawText 0 15 "Should be clipped"
drawText 0 25 "Should be clipped"
drawText 0 35 "Should be clipped"
drawText 0 45 "Should be clipped"
drawText 0 55 "Should be clipped"
end_block
translate 0 100
# rect replaced by x
save
setClipRect 1000 1000 10 10 ReplaceClip
setClipRect 20 10 60 30 ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipRect 1000 1000 10 10 ReplaceClip
setClipRectF 20 10 60 30 ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipRect 1000 1000 10 10 ReplaceClip
setClipRegion realRegion ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipRect 1000 1000 10 10 ReplaceClip
setClipPath realPath ReplaceClip
repeat_block paintstuff
restore
translate 100 0
# rectF replaced by x
save
setClipRectF 1000 1000 10 10 ReplaceClip
setClipRect 20 10 60 30 ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipRectF 1000 1000 10 10 ReplaceClip
setClipRectF 20 10 60 30 ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipRectF 1000 1000 10 10 ReplaceClip
setClipRegion realRegion ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipRectF 1000 1000 10 10 ReplaceClip
setClipPath realPath ReplaceClip
repeat_block paintstuff
restore
translate 100 0
translate -800 100
# region replaced by x
save
setClipRegion dummyRegion ReplaceClip
setClipRect 20 10 60 30 ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipRegion dummyRegion ReplaceClip
setClipRectF 20 10 60 30 ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipRegion dummyRegion ReplaceClip
setClipRegion realRegion ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipRegion dummyRegion ReplaceClip
setClipPath realPath ReplaceClip
repeat_block paintstuff
restore
translate 100 0
# path replaced by x
save
setClipPath dummyPath ReplaceClip
setClipRect 20 10 60 30 ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipPath dummyPath ReplaceClip
setClipRectF 20 10 60 30 ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipPath dummyPath ReplaceClip
setClipRegion realRegion ReplaceClip
repeat_block paintstuff
restore
translate 100 0
save
setClipPath dummyPath ReplaceClip
setClipPath realPath ReplaceClip
repeat_block paintstuff
restore
translate 100 0
region_addRect intregion 0 10 60 30
path_addRect intpath 0 10 60 30
translate -800 100
# rect & x
save
setClipRect 0 10 60 30 ReplaceClip
translate 40 0
setClipRect 0 10 60 30 IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipRect 0 10 60 30 ReplaceClip
translate 40 0
setClipRectF 0 10 60 30 IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipRect 0 10 60 30 ReplaceClip
translate 40 0
setClipRegion intregion IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipRect 0 10 60 30 ReplaceClip
translate 40 0
setClipPath intpath IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
# rectF & x
save
setClipRectF 0 10 60 30 ReplaceClip
translate 40 0
setClipRect 0 10 60 30 IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipRectF 0 10 60 30 ReplaceClip
translate 40 0
setClipRectF 0 10 60 30 IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipRectF 0 10 60 30 ReplaceClip
translate 40 0
setClipRegion intregion IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipRectF 0 10 60 30 ReplaceClip
translate 40 0
setClipPath intpath IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
translate -800 100
# region & x
save
setClipRegion intregion ReplaceClip
translate 40 0
setClipRect 0 10 60 30 IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipRegion intregion ReplaceClip
translate 40 0
setClipRectF 0 10 60 30 IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipRegion intregion ReplaceClip
translate 40 0
setClipRegion intregion IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipRegion intregion ReplaceClip
translate 40 0
setClipPath intpath IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
# path & x
save
setClipPath intpath ReplaceClip
translate 40 0
setClipRect 0 10 60 30 IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipPath intpath ReplaceClip
translate 40 0
setClipRectF 0 10 60 30 IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipPath intpath ReplaceClip
translate 40 0
setClipRegion intregion IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0
save
setClipPath intpath ReplaceClip
translate 40 0
setClipPath intpath IntersectClip
translate -40 0
repeat_block paintstuff
restore
translate 100 0

View File

@ -564,8 +564,12 @@ void PaintCommands::staticInit()
"setClipPath mypath ReplaceClip");
DECL_PAINTCOMMAND("setClipRect", command_setClipRect,
"^setClipRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(\\w*)$",
"setClipRect <x1> <y1> <x2> <y2> <clip operation enum>",
"setClipRect 0.0 0.0 10.0 10.0 ReplaceClip");
"setClipRect <x> <y> <w> <h> <clip operation enum>",
"setClipRect 0 0 10 10 ReplaceClip");
DECL_PAINTCOMMAND("setClipRectF", command_setClipRectF,
"^setClipRectF\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s*(\\w.*)$",
"setClipRectF <x> <y> <w> <h> <clip operation enum>",
"setClipRectF 0.1 0.2 10.3 10.4 ReplaceClip");
DECL_PAINTCOMMAND("setClipping", command_setClipping,
"^setClipping\\s+(\\w*)$",
"setClipping <true|false>",
@ -2081,6 +2085,25 @@ void PaintCommands::command_setClipRect(QRegularExpressionMatch re)
m_painter->setClipRect(x, y, w, h, Qt::ClipOperation(combine));
}
/***************************************************************************************************/
void PaintCommands::command_setClipRectF(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
double x = convertToDouble(caps.at(1));
double y = convertToDouble(caps.at(2));
double w = convertToDouble(caps.at(3));
double h = convertToDouble(caps.at(4));
int combine = translateEnum(clipOperationTable, caps.at(5), Qt::IntersectClip + 1);
if (combine == -1)
combine = Qt::ReplaceClip;
if (m_verboseMode)
printf(" -(lance) setClipRectF(%f, %f, %f, %f), %s\n", x, y, w, h, clipOperationTable[combine]);
m_painter->setClipRect(QRectF(x, y, w, h), Qt::ClipOperation(combine));
}
/***************************************************************************************************/
void PaintCommands::command_setClipPath(QRegularExpressionMatch re)
{

View File

@ -162,7 +162,7 @@ private:
void command_brushShear(QRegularExpressionMatch re);
void command_setClipPath(QRegularExpressionMatch re);
void command_setClipRect(QRegularExpressionMatch re);
void command_setClipRectangle(QRegularExpressionMatch re);
void command_setClipRectF(QRegularExpressionMatch re);
void command_setClipRegion(QRegularExpressionMatch re);
void command_setClipping(QRegularExpressionMatch re);
void command_setCompositionMode(QRegularExpressionMatch re);

View File

@ -1,4 +1,4 @@
LANCELOT_DIR = $$PWD/../../baseline/painting
LANCELOT_DIR = $$[QT_HOST_PREFIX]/tests/baseline/shared
CONFIG += cmdline moc
TEMPLATE = app
INCLUDEPATH += . $$LANCELOT_DIR
@ -11,7 +11,7 @@ SOURCES += interactivewidget.cpp \
main.cpp \
$$LANCELOT_DIR/paintcommands.cpp
RESOURCES += icons.qrc \
$$LANCELOT_DIR/images.qrc
$$LANCELOT_DIR/../painting/images.qrc
qtHaveModule(opengl): QT += opengl