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:
Eirik Aavitsland 2017-05-09 12:15:52 +02:00 committed by Allan Sandfeld Jensen
parent 8eccd1b0ad
commit 5dc0e4b285
4 changed files with 235 additions and 51 deletions

View File

@ -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) {
if (g->coordinateMode() == QGradient::StretchToDeviceMode) {
QBrush copy = brush; QBrush copy = brush;
QTransform mat = copy.transform(); const QPaintDevice *d = real_engine->painter()->device();
mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height()); QRectF r = (coMode == QGradient::ObjectBoundingMode) ? path.controlPointRect() : QRectF(0, 0, d->width(), d->height());
copy.setTransform(mat); combineXForm(&copy, r);
real_engine->fill(path, copy); real_engine->fill(path, copy);
return; 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());
brush.setTransform(mat);
copy.setBrush(brush); copy.setBrush(brush);
real_engine->stroke(path, copy); real_engine->stroke(path, copy);
return; 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());
} else if (g.coordinateMode() == QGradient::ObjectBoundingMode) {
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
QRectF r(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal()); QRectF r = (g.coordinateMode() == QGradient::ObjectBoundingMode) ?
mat.translate(r.x(), r.y()); QRectF(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal()) :
mat.scale(r.width(), r.height()); QRectF(0, 0, d->width(), d->height());
} combineXForm(&copy, r);
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);

View 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

View 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

View 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