Direct2D QPA: Stroke using direct2d primitives

Use native direct2d stroking instead of falling back to
QPaintEngineEx::stroke which in turn calls the pure virtual
QPaintEngineEx::fill which is reimplemented in QWindowsDirect2DPaintEngine.

In some cases like arc stroking this is significantly faster (up to 3x in
my measurements) and results in better visual quality.

Change-Id: I1c86ff772ba591432ff6550c7c59704ace4f0e0f
Reviewed-by: Risto Avila <risto.avila@digia.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
This commit is contained in:
Louai Al-Khanji 2014-05-09 11:17:41 +03:00 committed by The Qt Project
parent 35766fbe47
commit 58caefa13e
2 changed files with 84 additions and 1 deletions

View File

@ -934,6 +934,33 @@ void QWindowsDirect2DPaintEngine::setState(QPainterState *s)
transformChanged();
}
void QWindowsDirect2DPaintEngine::draw(const QVectorPath &path)
{
Q_D(QWindowsDirect2DPaintEngine);
ComPtr<ID2D1Geometry> geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED);
if (!geometry) {
qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__);
return;
}
const QBrush &brush = state()->brush;
if (qbrush_style(brush) != Qt::NoBrush) {
if (emulationRequired(BrushEmulation))
rasterFill(path, brush);
else
fill(geometry.Get(), brush);
}
const QPen &pen = state()->pen;
if (qpen_style(pen) != Qt::NoPen && qbrush_style(qpen_brush(pen)) != Qt::NoBrush) {
if (emulationRequired(PenEmulation))
QPaintEngineEx::stroke(path, pen);
else
stroke(geometry.Get(), pen);
}
}
void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
{
Q_D(QWindowsDirect2DPaintEngine);
@ -943,7 +970,6 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br
return;
ensureBrush(brush);
if (emulationRequired(BrushEmulation)) {
rasterFill(path, brush);
return;
@ -961,6 +987,56 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br
d->dc()->FillGeometry(geometry.Get(), d->brush.brush.Get());
}
void QWindowsDirect2DPaintEngine::fill(ID2D1Geometry *geometry, const QBrush &brush)
{
Q_D(QWindowsDirect2DPaintEngine);
D2D_TAG(D2DDebugFillTag);
ensureBrush(brush);
if (!d->brush.brush)
return;
d->dc()->FillGeometry(geometry, d->brush.brush.Get());
}
void QWindowsDirect2DPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
{
Q_D(QWindowsDirect2DPaintEngine);
D2D_TAG(D2DDebugFillTag);
if (path.isEmpty())
return;
ensurePen(pen);
if (emulationRequired(PenEmulation)) {
QPaintEngineEx::stroke(path, pen);
return;
}
if (!d->pen.brush)
return;
ComPtr<ID2D1Geometry> geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED);
if (!geometry) {
qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__);
return;
}
d->dc()->DrawGeometry(geometry.Get(), d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
}
void QWindowsDirect2DPaintEngine::stroke(ID2D1Geometry *geometry, const QPen &pen)
{
Q_D(QWindowsDirect2DPaintEngine);
D2D_TAG(D2DDebugFillTag);
ensurePen(pen);
if (!d->pen.brush)
return;
d->dc()->DrawGeometry(geometry, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
}
void QWindowsDirect2DPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
{
Q_D(QWindowsDirect2DPaintEngine);

View File

@ -68,7 +68,14 @@ public:
void setState(QPainterState *s) Q_DECL_OVERRIDE;
void draw(const QVectorPath &path) Q_DECL_OVERRIDE;
void fill(const QVectorPath &path, const QBrush &brush) Q_DECL_OVERRIDE;
void fill(ID2D1Geometry *geometry, const QBrush &brush);
void stroke(const QVectorPath &path, const QPen &pen) Q_DECL_OVERRIDE;
void stroke(ID2D1Geometry *geometry, const QPen &pen);
void clip(const QVectorPath &path, Qt::ClipOperation op) Q_DECL_OVERRIDE;
void clipEnabledChanged() Q_DECL_OVERRIDE;