Direct2D QPA: Add handlers for individual primitives
Directly handling primitives is faster than using the catch-all fill function which converts arbitrary paths into a direct2d geometry. So do so. Change-Id: I71ce73dbe75aa9b61e741c358d8787d0ea48ee46 Reviewed-by: Risto Avila <risto.avila@digia.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: Andrew Knight <andrew.knight@digia.com>bb10
parent
d52b00e1d3
commit
948fa572de
|
|
@ -72,8 +72,15 @@ QT_BEGIN_NAMESPACE
|
|||
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd370979(v=vs.85).aspx
|
||||
enum {
|
||||
D2DDebugDrawInitialStateTag = -1,
|
||||
D2DDebugDrawImageTag = 1,
|
||||
D2DDebugFillTag,
|
||||
D2DDebugFillTag = 1,
|
||||
D2DDebugFillRectTag,
|
||||
D2DDebugDrawRectsTag,
|
||||
D2DDebugDrawRectFsTag,
|
||||
D2DDebugDrawLinesTag,
|
||||
D2DDebugDrawLineFsTag,
|
||||
D2DDebugDrawEllipseTag,
|
||||
D2DDebugDrawEllipseFTag,
|
||||
D2DDebugDrawImageTag,
|
||||
D2DDebugDrawPixmapTag,
|
||||
D2DDebugDrawStaticTextItemTag,
|
||||
D2DDebugDrawTextItemTag
|
||||
|
|
@ -933,7 +940,7 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br
|
|||
|
||||
ensureBrush(brush);
|
||||
|
||||
if (!state()->matrix.isAffine() || d->brush.emulate) {
|
||||
if (emulationRequired(BrushEmulation)) {
|
||||
rasterFill(path, brush);
|
||||
return;
|
||||
}
|
||||
|
|
@ -941,25 +948,13 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br
|
|||
if (!d->brush.brush)
|
||||
return;
|
||||
|
||||
if (path.isRect()) {
|
||||
const qreal * const points = path.points();
|
||||
D2D_RECT_F rect = {
|
||||
points[0], // left
|
||||
points[1], // top
|
||||
points[2], // right,
|
||||
points[5] // bottom
|
||||
};
|
||||
|
||||
d->dc()->FillRectangle(rect, d->brush.brush.Get());
|
||||
} else {
|
||||
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()->FillGeometry(geometry.Get(), d->brush.brush.Get());
|
||||
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()->FillGeometry(geometry.Get(), d->brush.brush.Get());
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
|
||||
|
|
@ -1016,6 +1011,198 @@ void QWindowsDirect2DPaintEngine::transformChanged()
|
|||
d->updateTransform(state()->transform());
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
|
||||
{
|
||||
Q_D(QWindowsDirect2DPaintEngine);
|
||||
D2D_TAG(D2DDebugFillRectTag);
|
||||
|
||||
ensureBrush(brush);
|
||||
|
||||
if (emulationRequired(BrushEmulation)) {
|
||||
QPaintEngineEx::fillRect(rect, brush);
|
||||
} else {
|
||||
QRectF r = rect.normalized();
|
||||
adjustForAliasing(&r);
|
||||
|
||||
if (d->brush.brush)
|
||||
d->dc()->FillRectangle(to_d2d_rect_f(rect), d->brush.brush.Get());
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::drawRects(const QRect *rects, int rectCount)
|
||||
{
|
||||
Q_D(QWindowsDirect2DPaintEngine);
|
||||
D2D_TAG(D2DDebugDrawRectsTag);
|
||||
|
||||
ensureBrush();
|
||||
ensurePen();
|
||||
|
||||
if (emulationRequired(BrushEmulation) || emulationRequired(PenEmulation)) {
|
||||
QPaintEngineEx::drawRects(rects, rectCount);
|
||||
} else {
|
||||
QRectF rect;
|
||||
for (int i = 0; i < rectCount; i++) {
|
||||
rect = rects[i].normalized();
|
||||
adjustForAliasing(&rect);
|
||||
|
||||
D2D1_RECT_F d2d_rect = to_d2d_rect_f(rect);
|
||||
|
||||
if (d->brush.brush)
|
||||
d->dc()->FillRectangle(d2d_rect, d->brush.brush.Get());
|
||||
|
||||
if (d->pen.brush)
|
||||
d->dc()->DrawRectangle(d2d_rect, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::drawRects(const QRectF *rects, int rectCount)
|
||||
{
|
||||
Q_D(QWindowsDirect2DPaintEngine);
|
||||
D2D_TAG(D2DDebugDrawRectFsTag);
|
||||
|
||||
ensureBrush();
|
||||
ensurePen();
|
||||
|
||||
if (emulationRequired(BrushEmulation) || emulationRequired(PenEmulation)) {
|
||||
QPaintEngineEx::drawRects(rects, rectCount);
|
||||
} else {
|
||||
QRectF rect;
|
||||
for (int i = 0; i < rectCount; i++) {
|
||||
rect = rects[i].normalized();
|
||||
adjustForAliasing(&rect);
|
||||
|
||||
D2D1_RECT_F d2d_rect = to_d2d_rect_f(rect);
|
||||
|
||||
if (d->brush.brush)
|
||||
d->dc()->FillRectangle(d2d_rect, d->brush.brush.Get());
|
||||
|
||||
if (d->pen.brush)
|
||||
d->dc()->DrawRectangle(d2d_rect, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::drawLines(const QLine *lines, int lineCount)
|
||||
{
|
||||
Q_D(QWindowsDirect2DPaintEngine);
|
||||
D2D_TAG(D2DDebugDrawLinesTag);
|
||||
|
||||
ensurePen();
|
||||
|
||||
if (emulationRequired(PenEmulation)) {
|
||||
QPaintEngineEx::drawLines(lines, lineCount);
|
||||
} else if (d->pen.brush) {
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
QPointF p1 = lines[i].p1();
|
||||
QPointF p2 = lines[i].p2();
|
||||
|
||||
// Match raster engine output
|
||||
if (p1 == p2 && d->pen.qpen.widthF() <= 1.0) {
|
||||
fillRect(QRectF(p1, QSizeF(d->pen.qpen.widthF(), d->pen.qpen.widthF())),
|
||||
d->pen.qpen.brush());
|
||||
continue;
|
||||
}
|
||||
|
||||
adjustForAliasing(&p1);
|
||||
adjustForAliasing(&p2);
|
||||
|
||||
D2D1_POINT_2F d2d_p1 = to_d2d_point_2f(p1);
|
||||
D2D1_POINT_2F d2d_p2 = to_d2d_point_2f(p2);
|
||||
|
||||
d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::drawLines(const QLineF *lines, int lineCount)
|
||||
{
|
||||
Q_D(QWindowsDirect2DPaintEngine);
|
||||
D2D_TAG(D2DDebugDrawLineFsTag);
|
||||
|
||||
ensurePen();
|
||||
|
||||
if (emulationRequired(PenEmulation)) {
|
||||
QPaintEngineEx::drawLines(lines, lineCount);
|
||||
} else if (d->pen.brush) {
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
QPointF p1 = lines[i].p1();
|
||||
QPointF p2 = lines[i].p2();
|
||||
|
||||
// Match raster engine output
|
||||
if (p1 == p2 && d->pen.qpen.widthF() <= 1.0) {
|
||||
fillRect(QRectF(p1, QSizeF(d->pen.qpen.widthF(), d->pen.qpen.widthF())),
|
||||
d->pen.qpen.brush());
|
||||
continue;
|
||||
}
|
||||
|
||||
adjustForAliasing(&p1);
|
||||
adjustForAliasing(&p2);
|
||||
|
||||
D2D1_POINT_2F d2d_p1 = to_d2d_point_2f(p1);
|
||||
D2D1_POINT_2F d2d_p2 = to_d2d_point_2f(p2);
|
||||
|
||||
d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::drawEllipse(const QRectF &r)
|
||||
{
|
||||
Q_D(QWindowsDirect2DPaintEngine);
|
||||
D2D_TAG(D2DDebugDrawEllipseFTag);
|
||||
|
||||
ensureBrush();
|
||||
ensurePen();
|
||||
|
||||
if (emulationRequired(BrushEmulation) || emulationRequired(PenEmulation)) {
|
||||
QPaintEngineEx::drawEllipse(r);
|
||||
} else {
|
||||
QPointF p = r.center();
|
||||
adjustForAliasing(&p);
|
||||
|
||||
D2D1_ELLIPSE ellipse = {
|
||||
to_d2d_point_2f(p),
|
||||
r.width() / 2.0,
|
||||
r.height() / 2.0
|
||||
};
|
||||
|
||||
if (d->brush.brush)
|
||||
d->dc()->FillEllipse(ellipse, d->brush.brush.Get());
|
||||
|
||||
if (d->pen.brush)
|
||||
d->dc()->DrawEllipse(ellipse, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::drawEllipse(const QRect &r)
|
||||
{
|
||||
Q_D(QWindowsDirect2DPaintEngine);
|
||||
D2D_TAG(D2DDebugDrawEllipseTag);
|
||||
|
||||
ensureBrush();
|
||||
ensurePen();
|
||||
|
||||
if (emulationRequired(BrushEmulation) || emulationRequired(PenEmulation)) {
|
||||
QPaintEngineEx::drawEllipse(r);
|
||||
} else {
|
||||
QPointF p = r.center();
|
||||
adjustForAliasing(&p);
|
||||
|
||||
D2D1_ELLIPSE ellipse = {
|
||||
to_d2d_point_2f(p),
|
||||
r.width() / 2.0,
|
||||
r.height() / 2.0
|
||||
};
|
||||
|
||||
if (d->brush.brush)
|
||||
d->dc()->FillEllipse(ellipse, d->brush.brush.Get());
|
||||
|
||||
if (d->pen.brush)
|
||||
d->dc()->DrawEllipse(ellipse, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::drawImage(const QRectF &rectangle, const QImage &image,
|
||||
const QRectF &sr, Qt::ImageConversionFlags flags)
|
||||
{
|
||||
|
|
@ -1388,4 +1575,47 @@ void QWindowsDirect2DPaintEngine::rasterFill(const QVectorPath &path, const QBru
|
|||
}
|
||||
}
|
||||
|
||||
bool QWindowsDirect2DPaintEngine::emulationRequired(EmulationType type) const
|
||||
{
|
||||
Q_D(const QWindowsDirect2DPaintEngine);
|
||||
|
||||
if (!state()->matrix.isAffine())
|
||||
return true;
|
||||
|
||||
switch (type) {
|
||||
case PenEmulation:
|
||||
return d->pen.emulate;
|
||||
break;
|
||||
case BrushEmulation:
|
||||
return d->brush.emulate;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QWindowsDirect2DPaintEngine::antiAliasingEnabled() const
|
||||
{
|
||||
return state()->renderHints & QPainter::Antialiasing;
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::adjustForAliasing(QRectF *rect)
|
||||
{
|
||||
if (!antiAliasingEnabled()) {
|
||||
rect->adjust(MAGICAL_ALIASING_OFFSET,
|
||||
MAGICAL_ALIASING_OFFSET,
|
||||
MAGICAL_ALIASING_OFFSET,
|
||||
MAGICAL_ALIASING_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsDirect2DPaintEngine::adjustForAliasing(QPointF *point)
|
||||
{
|
||||
static const QPointF adjustment(MAGICAL_ALIASING_OFFSET,
|
||||
MAGICAL_ALIASING_OFFSET);
|
||||
|
||||
if (!antiAliasingEnabled())
|
||||
(*point) += adjustment;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -79,6 +79,17 @@ public:
|
|||
void renderHintsChanged() Q_DECL_OVERRIDE;
|
||||
void transformChanged() Q_DECL_OVERRIDE;
|
||||
|
||||
void fillRect(const QRectF &rect, const QBrush &brush) Q_DECL_OVERRIDE;
|
||||
|
||||
void drawRects(const QRect *rects, int rectCount) Q_DECL_OVERRIDE;
|
||||
void drawRects(const QRectF *rects, int rectCount) Q_DECL_OVERRIDE;
|
||||
|
||||
void drawLines(const QLine *lines, int lineCount) Q_DECL_OVERRIDE;
|
||||
void drawLines(const QLineF *lines, int lineCount) Q_DECL_OVERRIDE;
|
||||
|
||||
void drawEllipse(const QRectF &r) Q_DECL_OVERRIDE;
|
||||
void drawEllipse(const QRect &r) Q_DECL_OVERRIDE;
|
||||
|
||||
void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE;
|
||||
void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) Q_DECL_OVERRIDE;
|
||||
|
||||
|
|
@ -96,6 +107,13 @@ private:
|
|||
void ensurePen(const QPen &pen);
|
||||
|
||||
void rasterFill(const QVectorPath &path, const QBrush &brush);
|
||||
|
||||
enum EmulationType { PenEmulation, BrushEmulation };
|
||||
bool emulationRequired(EmulationType type) const;
|
||||
|
||||
bool antiAliasingEnabled() const;
|
||||
void adjustForAliasing(QRectF *rect);
|
||||
void adjustForAliasing(QPointF *point);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
Loading…
Reference in New Issue