Direct2D QPA: Improve gradient support

This change adds support for those gradients which can be expressed using
Direct2D. At the moment this means linear and radial gradient with pad
spread only.

Change-Id: Ib1b1bc38a793dd826a259bbf8a7b31c25906dd59
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
This commit is contained in:
Louai Al-Khanji 2014-04-07 14:11:27 +03:00 committed by The Qt Project
parent cd21b56c9d
commit f961425256

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@ -658,7 +658,91 @@ public:
break;
case Qt::LinearGradientPattern:
if (newBrush.gradient()->spread() != QGradient::PadSpread) {
*needsEmulation = true;
} else {
ComPtr<ID2D1LinearGradientBrush> linear;
const QLinearGradient *qlinear = static_cast<const QLinearGradient *>(newBrush.gradient());
D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES linearGradientBrushProperties;
ComPtr<ID2D1GradientStopCollection> gradientStopCollection;
const QGradientStops &qstops = qlinear->stops();
QVector<D2D1_GRADIENT_STOP> stops(qstops.count());
linearGradientBrushProperties.startPoint = to_d2d_point_2f(qlinear->start());
linearGradientBrushProperties.endPoint = to_d2d_point_2f(qlinear->finalStop());
for (int i = 0; i < stops.size(); i++) {
stops[i].position = qstops[i].first;
stops[i].color = to_d2d_color_f(qstops[i].second);
}
hr = dc()->CreateGradientStopCollection(stops.constData(), stops.size(), &gradientStopCollection);
if (FAILED(hr)) {
qWarning("%s: Could not create gradient stop collection for linear gradient: %#x", __FUNCTION__, hr);
break;
}
hr = dc()->CreateLinearGradientBrush(linearGradientBrushProperties, gradientStopCollection.Get(),
&linear);
if (FAILED(hr)) {
qWarning("%s: Could not create Direct2D linear gradient brush: %#x", __FUNCTION__, hr);
break;
}
hr = linear.As(&result);
if (FAILED(hr)) {
qWarning("%s: Could not convert Direct2D linear gradient brush: %#x", __FUNCTION__, hr);
break;
}
}
break;
case Qt::RadialGradientPattern:
if (newBrush.gradient()->spread() != QGradient::PadSpread) {
*needsEmulation = true;
} else {
ComPtr<ID2D1RadialGradientBrush> radial;
const QRadialGradient *qradial = static_cast<const QRadialGradient *>(newBrush.gradient());
D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES radialGradientBrushProperties;
ComPtr<ID2D1GradientStopCollection> gradientStopCollection;
const QGradientStops &qstops = qradial->stops();
QVector<D2D1_GRADIENT_STOP> stops(qstops.count());
radialGradientBrushProperties.center = to_d2d_point_2f(qradial->center());
radialGradientBrushProperties.gradientOriginOffset = to_d2d_point_2f(qradial->focalPoint() - qradial->center());
radialGradientBrushProperties.radiusX = qradial->radius();
radialGradientBrushProperties.radiusY = qradial->radius();
for (int i = 0; i < stops.size(); i++) {
stops[i].position = qstops[i].first;
stops[i].color = to_d2d_color_f(qstops[i].second);
}
hr = dc()->CreateGradientStopCollection(stops.constData(), stops.size(), &gradientStopCollection);
if (FAILED(hr)) {
qWarning("%s: Could not create gradient stop collection for radial gradient: %#x", __FUNCTION__, hr);
break;
}
hr = dc()->CreateRadialGradientBrush(radialGradientBrushProperties, gradientStopCollection.Get(),
&radial);
if (FAILED(hr)) {
qWarning("%s: Could not create Direct2D radial gradient brush: %#x", __FUNCTION__, hr);
break;
}
radial.As(&result);
if (FAILED(hr)) {
qWarning("%s: Could not convert Direct2D radial gradient brush: %#x", __FUNCTION__, hr);
break;
}
}
break;
case Qt::ConicalGradientPattern:
*needsEmulation = true;
break;
@ -706,16 +790,9 @@ QWindowsDirect2DPaintEngine::QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap
: QPaintEngineEx(*(new QWindowsDirect2DPaintEnginePrivate(bitmap)))
{
QPaintEngine::PaintEngineFeatures unsupported =
// As of 1.1 Direct2D gradient support is deficient for linear and radial gradients
QPaintEngine::LinearGradientFill
| QPaintEngine::RadialGradientFill
// As of 1.1 Direct2D does not support conical gradients at all
| QPaintEngine::ConicalGradientFill
// As of 1.1 Direct2D does not natively support complex composition modes
// However, using Direct2D effects that implement them should be possible
| QPaintEngine::PorterDuff
QPaintEngine::PorterDuff
| QPaintEngine::BlendModes
| QPaintEngine::RasterOpModes
@ -796,7 +873,7 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br
if (d->brush.emulate) {
// We mostly (only?) get here when gradients are required.
// We could probably natively support linear and radial gradients that have pad reflect
// We natively support only linear and radial gradients that have pad reflect due to D2D limitations
QImage img(d->bitmap->size(), QImage::Format_ARGB32);
img.fill(Qt::transparent);