Simplify code by factoring out brush transformation for gradients
Emulation of non-logical coordinate mode gradients was implemented by essentially 3 x 2 repetitions of the same manipulation of the QBrush transform. Avoid the code duplication by extracting a common method. Add lancelot test scripts that excersizes these code paths. Change-Id: I7baa921923231ef9e83e443dba996b82b32ad1e7 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
parent
8eccd1b0ad
commit
5dc0e4b285
@ -72,6 +72,14 @@ QPainterState *QEmulationPaintEngine::createState(QPainterState *orig) const
|
|||||||
return real_engine->createState(orig);
|
return real_engine->createState(orig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void combineXForm(QBrush *brush, const QRectF &r)
|
||||||
|
{
|
||||||
|
QTransform t = brush->transform();
|
||||||
|
t.translate(r.x(), r.y());
|
||||||
|
t.scale(r.width(), r.height());
|
||||||
|
brush->setTransform(t);
|
||||||
|
}
|
||||||
|
|
||||||
void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
|
void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
|
||||||
{
|
{
|
||||||
QPainterState *s = state();
|
QPainterState *s = state();
|
||||||
@ -84,26 +92,14 @@ void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
|
|||||||
|
|
||||||
Qt::BrushStyle style = qbrush_style(brush);
|
Qt::BrushStyle style = qbrush_style(brush);
|
||||||
if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
|
if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
|
||||||
const QGradient *g = brush.gradient();
|
QGradient::CoordinateMode coMode = brush.gradient()->coordinateMode();
|
||||||
|
if (coMode > QGradient::LogicalMode) {
|
||||||
if (g->coordinateMode() > QGradient::LogicalMode) {
|
QBrush copy = brush;
|
||||||
if (g->coordinateMode() == QGradient::StretchToDeviceMode) {
|
const QPaintDevice *d = real_engine->painter()->device();
|
||||||
QBrush copy = brush;
|
QRectF r = (coMode == QGradient::ObjectBoundingMode) ? path.controlPointRect() : QRectF(0, 0, d->width(), d->height());
|
||||||
QTransform mat = copy.transform();
|
combineXForm(©, r);
|
||||||
mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height());
|
real_engine->fill(path, copy);
|
||||||
copy.setTransform(mat);
|
return;
|
||||||
real_engine->fill(path, copy);
|
|
||||||
return;
|
|
||||||
} else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
|
|
||||||
QBrush copy = brush;
|
|
||||||
QTransform mat = copy.transform();
|
|
||||||
QRectF r = path.controlPointRect();
|
|
||||||
mat.translate(r.x(), r.y());
|
|
||||||
mat.scale(r.width(), r.height());
|
|
||||||
copy.setTransform(mat);
|
|
||||||
real_engine->fill(path, copy);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,27 +120,15 @@ void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
|
|||||||
QBrush brush = pen.brush();
|
QBrush brush = pen.brush();
|
||||||
QPen copy = pen;
|
QPen copy = pen;
|
||||||
Qt::BrushStyle style = qbrush_style(brush);
|
Qt::BrushStyle style = qbrush_style(brush);
|
||||||
if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
|
if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern ) {
|
||||||
const QGradient *g = brush.gradient();
|
QGradient::CoordinateMode coMode = brush.gradient()->coordinateMode();
|
||||||
|
if (coMode > QGradient::LogicalMode) {
|
||||||
if (g->coordinateMode() > QGradient::LogicalMode) {
|
const QPaintDevice *d = real_engine->painter()->device();
|
||||||
if (g->coordinateMode() == QGradient::StretchToDeviceMode) {
|
QRectF r = (coMode == QGradient::ObjectBoundingMode) ? path.controlPointRect() : QRectF(0, 0, d->width(), d->height());
|
||||||
QTransform mat = brush.transform();
|
combineXForm(&brush, r);
|
||||||
mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height());
|
copy.setBrush(brush);
|
||||||
brush.setTransform(mat);
|
real_engine->stroke(path, copy);
|
||||||
copy.setBrush(brush);
|
return;
|
||||||
real_engine->stroke(path, copy);
|
|
||||||
return;
|
|
||||||
} else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
|
|
||||||
QTransform mat = brush.transform();
|
|
||||||
QRectF r = path.controlPointRect();
|
|
||||||
mat.translate(r.x(), r.y());
|
|
||||||
mat.scale(r.width(), r.height());
|
|
||||||
brush.setTransform(mat);
|
|
||||||
copy.setBrush(brush);
|
|
||||||
real_engine->stroke(path, copy);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,18 +163,16 @@ void QEmulationPaintEngine::drawTextItem(const QPointF &p, const QTextItem &text
|
|||||||
QGradient g = *s->pen.brush().gradient();
|
QGradient g = *s->pen.brush().gradient();
|
||||||
|
|
||||||
if (g.coordinateMode() > QGradient::LogicalMode) {
|
if (g.coordinateMode() > QGradient::LogicalMode) {
|
||||||
QTransform mat = s->pen.brush().transform();
|
QBrush copy = s->pen.brush();
|
||||||
if (g.coordinateMode() == QGradient::StretchToDeviceMode) {
|
const QPaintDevice *d = real_engine->painter()->device();
|
||||||
mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height());
|
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
|
||||||
} else if (g.coordinateMode() == QGradient::ObjectBoundingMode) {
|
QRectF r = (g.coordinateMode() == QGradient::ObjectBoundingMode) ?
|
||||||
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
|
QRectF(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal()) :
|
||||||
QRectF r(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
|
QRectF(0, 0, d->width(), d->height());
|
||||||
mat.translate(r.x(), r.y());
|
combineXForm(©, r);
|
||||||
mat.scale(r.width(), r.height());
|
|
||||||
}
|
|
||||||
g.setCoordinateMode(QGradient::LogicalMode);
|
g.setCoordinateMode(QGradient::LogicalMode);
|
||||||
QBrush brush(g);
|
QBrush brush(g);
|
||||||
brush.setTransform(mat);
|
brush.setTransform(copy.transform());
|
||||||
s->pen.setBrush(brush);
|
s->pen.setBrush(brush);
|
||||||
penChanged();
|
penChanged();
|
||||||
real_engine->drawTextItem(p, textItem);
|
real_engine->drawTextItem(p, textItem);
|
||||||
|
67
tests/auto/other/lancelot/scripts/gradientxform_device.qps
Normal file
67
tests/auto/other/lancelot/scripts/gradientxform_device.qps
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# Version: 1
|
||||||
|
# CheckVsReference: 5%
|
||||||
|
|
||||||
|
gradient_clearStops
|
||||||
|
gradient_appendStop 0 black
|
||||||
|
gradient_appendStop 0.4 yellow
|
||||||
|
gradient_appendStop 1 gray
|
||||||
|
|
||||||
|
gradient_setSpread PadSpread
|
||||||
|
|
||||||
|
gradient_setCoordinateMode StretchToDeviceMode
|
||||||
|
|
||||||
|
# first run is dummy, make it offscreen
|
||||||
|
save
|
||||||
|
translate -500 -500
|
||||||
|
|
||||||
|
begin_block row
|
||||||
|
save
|
||||||
|
|
||||||
|
setPen nopen
|
||||||
|
drawRect 50 0 100 100
|
||||||
|
|
||||||
|
setPen brush 30
|
||||||
|
setBrush lightblue
|
||||||
|
drawRect 175 15 70 70
|
||||||
|
|
||||||
|
setFont "times" 110 99
|
||||||
|
drawText 270 100 "X"
|
||||||
|
|
||||||
|
restore
|
||||||
|
end_block row
|
||||||
|
|
||||||
|
restore
|
||||||
|
|
||||||
|
drawText 160 20 "PLAIN"
|
||||||
|
drawText 560 20 "BRUSH XFORM"
|
||||||
|
translate 0 20
|
||||||
|
|
||||||
|
begin_block block
|
||||||
|
save
|
||||||
|
|
||||||
|
drawText 75 20 "Brush Fill"
|
||||||
|
drawText 176 20 "Pen Stroke"
|
||||||
|
drawText 277 20 "Text Stroke"
|
||||||
|
translate 0 30
|
||||||
|
drawText 0 50 "Linear"
|
||||||
|
drawText 0 160 "Radial"
|
||||||
|
drawText 0 270 "Conical"
|
||||||
|
|
||||||
|
gradient_setLinear 0.0 0.0 0.4 0.0
|
||||||
|
repeat_block row
|
||||||
|
|
||||||
|
translate 0 110
|
||||||
|
gradient_setRadial 0.04 0.08 0.3 0.3 0.05
|
||||||
|
repeat_block row
|
||||||
|
|
||||||
|
translate 0 110
|
||||||
|
gradient_setConical 0.25 0.1 45
|
||||||
|
repeat_block row
|
||||||
|
restore
|
||||||
|
end_block block
|
||||||
|
|
||||||
|
translate 400 0
|
||||||
|
brushRotate 30.0
|
||||||
|
brushScale 1.5 .5
|
||||||
|
brushTranslate 0 -80
|
||||||
|
repeat_block block
|
67
tests/auto/other/lancelot/scripts/gradientxform_logical.qps
Normal file
67
tests/auto/other/lancelot/scripts/gradientxform_logical.qps
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# Version: 1
|
||||||
|
# CheckVsReference: 5%
|
||||||
|
|
||||||
|
gradient_clearStops
|
||||||
|
gradient_appendStop 0 black
|
||||||
|
gradient_appendStop 0.4 yellow
|
||||||
|
gradient_appendStop 1 gray
|
||||||
|
|
||||||
|
gradient_setSpread PadSpread
|
||||||
|
|
||||||
|
gradient_setCoordinateMode LogicalMode
|
||||||
|
|
||||||
|
# first run is dummy, make it offscreen
|
||||||
|
save
|
||||||
|
translate -500 -500
|
||||||
|
|
||||||
|
begin_block row
|
||||||
|
save
|
||||||
|
|
||||||
|
setPen nopen
|
||||||
|
drawRect 50 0 100 100
|
||||||
|
|
||||||
|
setPen brush 30
|
||||||
|
setBrush lightblue
|
||||||
|
drawRect 175 15 70 70
|
||||||
|
|
||||||
|
setFont "times" 110 99
|
||||||
|
drawText 270 100 "X"
|
||||||
|
|
||||||
|
restore
|
||||||
|
end_block row
|
||||||
|
|
||||||
|
restore
|
||||||
|
|
||||||
|
drawText 160 20 "PLAIN"
|
||||||
|
drawText 560 20 "BRUSH XFORM"
|
||||||
|
translate 0 20
|
||||||
|
|
||||||
|
begin_block block
|
||||||
|
save
|
||||||
|
|
||||||
|
drawText 75 20 "Brush Fill"
|
||||||
|
drawText 176 20 "Pen Stroke"
|
||||||
|
drawText 277 20 "Text Stroke"
|
||||||
|
translate 0 30
|
||||||
|
drawText 0 50 "Linear"
|
||||||
|
drawText 0 160 "Radial"
|
||||||
|
drawText 0 270 "Conical"
|
||||||
|
|
||||||
|
gradient_setLinear 0 0 400 0
|
||||||
|
repeat_block row
|
||||||
|
|
||||||
|
translate 0 110
|
||||||
|
gradient_setRadial 200 50 140 70 20
|
||||||
|
repeat_block row
|
||||||
|
|
||||||
|
translate 0 110
|
||||||
|
gradient_setConical 220 60 45
|
||||||
|
repeat_block row
|
||||||
|
restore
|
||||||
|
end_block block
|
||||||
|
|
||||||
|
translate 400 0
|
||||||
|
brushRotate 30.0
|
||||||
|
brushScale 1.5 .5
|
||||||
|
brushTranslate 0 -80
|
||||||
|
repeat_block block
|
68
tests/auto/other/lancelot/scripts/gradientxform_object.qps
Normal file
68
tests/auto/other/lancelot/scripts/gradientxform_object.qps
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# Version: 1
|
||||||
|
# CheckVsReference: 5%
|
||||||
|
|
||||||
|
gradient_clearStops
|
||||||
|
gradient_appendStop 0 black
|
||||||
|
gradient_appendStop 0.4 yellow
|
||||||
|
gradient_appendStop 1 gray
|
||||||
|
|
||||||
|
gradient_setSpread PadSpread
|
||||||
|
|
||||||
|
gradient_setCoordinateMode ObjectBoundingMode
|
||||||
|
|
||||||
|
# first run is dummy, make it offscreen
|
||||||
|
save
|
||||||
|
translate -500 -500
|
||||||
|
|
||||||
|
begin_block row
|
||||||
|
save
|
||||||
|
|
||||||
|
setPen nopen
|
||||||
|
drawRect 50 0 100 100
|
||||||
|
|
||||||
|
setPen brush 30
|
||||||
|
setBrush lightblue
|
||||||
|
translate 110 0
|
||||||
|
drawRect 65 15 70 70
|
||||||
|
|
||||||
|
translate 110 0
|
||||||
|
setFont "times" 110 99
|
||||||
|
drawText 50 100 "X"
|
||||||
|
|
||||||
|
restore
|
||||||
|
end_block row
|
||||||
|
|
||||||
|
restore
|
||||||
|
|
||||||
|
drawText 160 20 "PLAIN"
|
||||||
|
drawText 560 20 "BRUSH XFORM"
|
||||||
|
translate 0 20
|
||||||
|
|
||||||
|
begin_block block
|
||||||
|
save
|
||||||
|
|
||||||
|
drawText 75 20 "Brush Fill"
|
||||||
|
drawText 176 20 "Pen Stroke"
|
||||||
|
drawText 277 20 "Text Stroke"
|
||||||
|
translate 0 30
|
||||||
|
drawText 0 50 "Linear"
|
||||||
|
drawText 0 160 "Radial"
|
||||||
|
drawText 0 270 "Conical"
|
||||||
|
|
||||||
|
gradient_setLinear 0.1 0.0 0.5 0.0
|
||||||
|
repeat_block row
|
||||||
|
|
||||||
|
translate 0 110
|
||||||
|
gradient_setRadial 0.3 0.2 0.5 0.4 0.5
|
||||||
|
repeat_block row
|
||||||
|
|
||||||
|
translate 0 110
|
||||||
|
gradient_setConical 0.5 0.7 45
|
||||||
|
repeat_block row
|
||||||
|
restore
|
||||||
|
end_block block
|
||||||
|
|
||||||
|
translate 400 0
|
||||||
|
brushRotate 30.0
|
||||||
|
brushScale 1.5 .5
|
||||||
|
repeat_block block
|
Loading…
Reference in New Issue
Block a user