summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp')
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp405
1 files changed, 262 insertions, 143 deletions
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index 4c39560cbe..c13f0f333a 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -5,36 +5,28 @@
**
** This file is part of the plugins of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -48,11 +40,12 @@
#include "qwindowsdirect2ddevicecontext.h"
#include "qwindowsfontengine.h"
-#include "qwindowsfontenginedirectwrite.h"
#include "qwindowsfontdatabase.h"
#include "qwindowsintegration.h"
+#include <QtCore/QtMath>
#include <QtCore/QStack>
+#include <QtCore/QSettings>
#include <QtGui/private/qpaintengine_p.h>
#include <QtGui/private/qtextengine_p.h>
#include <QtGui/private/qfontengine_p.h>
@@ -109,6 +102,16 @@ static inline ID2D1Factory1 *factory()
return QWindowsDirect2DContext::instance()->d2dFactory();
}
+static inline D2D1_MATRIX_3X2_F transformFromLine(const QLineF &line, qreal penWidth)
+{
+ const qreal halfWidth = penWidth / 2;
+ const qreal angle = -qDegreesToRadians(line.angle());
+ QTransform transform = QTransform::fromTranslate(line.p1().x() + qSin(angle) * halfWidth,
+ line.p1().y() - qCos(angle) * halfWidth);
+ transform.rotateRadians(angle);
+ return to_d2d_matrix_3x2_f(transform);
+}
+
class Direct2DPathGeometryWriter
{
public:
@@ -226,9 +229,10 @@ class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate
{
Q_DECLARE_PUBLIC(QWindowsDirect2DPaintEngine)
public:
- QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm)
+ QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm, QWindowsDirect2DPaintEngine::Flags flags)
: bitmap(bm)
, clipFlags(0)
+ , flags(flags)
{
pen.reset();
brush.reset();
@@ -237,25 +241,29 @@ public:
}
QWindowsDirect2DBitmap *bitmap;
+ QImage fallbackImage;
unsigned int clipFlags;
QStack<ClipType> pushedClips;
+ QWindowsDirect2DPaintEngine::Flags flags;
QPointF currentBrushOrigin;
- QHash< QFont, ComPtr<IDWriteFontFace> > fontCache;
+ QHash< QFontDef, ComPtr<IDWriteFontFace> > fontCache;
struct {
bool emulate;
QPen qpen;
ComPtr<ID2D1Brush> brush;
ComPtr<ID2D1StrokeStyle1> strokeStyle;
+ ComPtr<ID2D1BitmapBrush1> dashBrush;
inline void reset() {
emulate = false;
qpen = QPen();
brush.Reset();
strokeStyle.Reset();
+ dashBrush.Reset();
}
} pen;
@@ -291,6 +299,14 @@ public:
: D2D1_ANTIALIAS_MODE_ALIASED;
}
+ inline D2D1_LAYER_OPTIONS1 layerOptions() const
+ {
+ if (flags & QWindowsDirect2DPaintEngine::TranslucentTopLevelWindow)
+ return D2D1_LAYER_OPTIONS1_NONE;
+ else
+ return D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
+ }
+
void updateTransform(const QTransform &transform)
{
dc()->SetTransform(to_d2d_matrix_3x2_f(transform));
@@ -336,7 +352,7 @@ public:
D2D1::IdentityMatrix(),
1.0,
NULL,
- D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND),
+ layerOptions()),
NULL);
pushedClips.push(LayerClip);
}
@@ -391,7 +407,10 @@ public:
break;
default:
- qWarning("Unsupported composition mode: %d", mode);
+ // Activating an unsupported mode at any time will cause the QImage
+ // fallback to be used for the remainder of the active paint session
+ dc()->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_COPY);
+ flags |= QWindowsDirect2DPaintEngine::EmulateComposition;
break;
}
}
@@ -522,12 +541,31 @@ public:
if (props.dashStyle == D2D1_DASH_STYLE_CUSTOM) {
QVector<qreal> dashes = newPen.dashPattern();
QVector<FLOAT> converted(dashes.size());
-
+ qreal penWidth = pen.qpen.widthF();
+ qreal brushWidth = 0;
for (int i = 0; i < dashes.size(); i++) {
converted[i] = dashes[i];
+ brushWidth += penWidth * dashes[i];
}
hr = factory()->CreateStrokeStyle(props, converted.constData(), converted.size(), &pen.strokeStyle);
+
+ // Create a combined brush/dash pattern for optimized line drawing
+ QWindowsDirect2DBitmap bitmap;
+ bitmap.resize(ceil(brushWidth), ceil(penWidth));
+ bitmap.deviceContext()->begin();
+ bitmap.deviceContext()->get()->SetAntialiasMode(antialiasMode());
+ bitmap.deviceContext()->get()->SetTransform(D2D1::IdentityMatrix());
+ bitmap.deviceContext()->get()->Clear();
+ const qreal offsetX = (qreal(bitmap.size().width()) - brushWidth) / 2;
+ const qreal offsetY = qreal(bitmap.size().height()) / 2;
+ bitmap.deviceContext()->get()->DrawLine(D2D1::Point2F(offsetX, offsetY),
+ D2D1::Point2F(brushWidth, offsetY),
+ pen.brush.Get(), penWidth, pen.strokeStyle.Get());
+ bitmap.deviceContext()->end();
+ D2D1_BITMAP_BRUSH_PROPERTIES1 bitmapBrushProperties = D2D1::BitmapBrushProperties1(
+ D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, D2D1_INTERPOLATION_MODE_LINEAR);
+ hr = dc()->CreateBitmapBrush(bitmap.bitmap(), bitmapBrushProperties, &pen.dashBrush);
} else {
hr = factory()->CreateStrokeStyle(props, NULL, 0, &pen.strokeStyle);
}
@@ -836,10 +874,79 @@ public:
{
dc()->SetAntialiasMode(antialiasMode());
}
+
+ void drawGlyphRun(const D2D1_POINT_2F &pos,
+ IDWriteFontFace *fontFace,
+ const QFontDef &fontDef,
+ int numGlyphs,
+ const UINT16 *glyphIndices,
+ const FLOAT *glyphAdvances,
+ const DWRITE_GLYPH_OFFSET *glyphOffsets,
+ bool rtl)
+ {
+ Q_Q(QWindowsDirect2DPaintEngine);
+
+ DWRITE_GLYPH_RUN glyphRun = {
+ fontFace, // IDWriteFontFace *fontFace;
+ fontDef.pixelSize, // FLOAT fontEmSize;
+ numGlyphs, // UINT32 glyphCount;
+ glyphIndices, // const UINT16 *glyphIndices;
+ glyphAdvances, // const FLOAT *glyphAdvances;
+ glyphOffsets, // const DWRITE_GLYPH_OFFSET *glyphOffsets;
+ FALSE, // BOOL isSideways;
+ rtl ? 1 : 0 // UINT32 bidiLevel;
+ };
+
+ const bool antiAlias = bool((q->state()->renderHints & QPainter::TextAntialiasing)
+ && !(fontDef.styleStrategy & QFont::NoAntialias));
+ const D2D1_TEXT_ANTIALIAS_MODE antialiasMode = (flags & QWindowsDirect2DPaintEngine::TranslucentTopLevelWindow)
+ ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
+ dc()->SetTextAntialiasMode(antiAlias ? antialiasMode : D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
+
+ dc()->DrawGlyphRun(pos,
+ &glyphRun,
+ NULL,
+ pen.brush.Get(),
+ DWRITE_MEASURING_MODE_GDI_CLASSIC);
+ }
+
+ ComPtr<IDWriteFontFace> fontFaceFromFontEngine(QFontEngine *fe)
+ {
+ const QFontDef fontDef = fe->fontDef;
+ ComPtr<IDWriteFontFace> fontFace = fontCache.value(fontDef);
+ if (fontFace)
+ return fontFace;
+
+ LOGFONT lf = QWindowsFontDatabase::fontDefToLOGFONT(fontDef);
+
+ // Get substitute name
+ static const char keyC[] = "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes";
+ const QString familyName = QString::fromWCharArray(lf.lfFaceName);
+ const QString nameSubstitute = QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString();
+ memcpy(lf.lfFaceName, nameSubstitute.utf16(), sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE));
+
+ ComPtr<IDWriteFont> dwriteFont;
+ HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFromLOGFONT(&lf, &dwriteFont);
+ if (FAILED(hr)) {
+ qDebug("%s: CreateFontFromLOGFONT failed: %#x", __FUNCTION__, hr);
+ return fontFace;
+ }
+
+ hr = dwriteFont->CreateFontFace(&fontFace);
+ if (FAILED(hr)) {
+ qDebug("%s: CreateFontFace failed: %#x", __FUNCTION__, hr);
+ return fontFace;
+ }
+
+ if (fontFace)
+ fontCache.insert(fontDef, fontFace);
+
+ return fontFace;
+ }
};
-QWindowsDirect2DPaintEngine::QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap)
- : QPaintEngineEx(*(new QWindowsDirect2DPaintEnginePrivate(bitmap)))
+QWindowsDirect2DPaintEngine::QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap, Flags flags)
+ : QPaintEngineEx(*(new QWindowsDirect2DPaintEnginePrivate(bitmap, flags)))
{
QPaintEngine::PaintEngineFeatures unsupported =
// As of 1.1 Direct2D does not natively support complex composition modes
@@ -878,7 +985,7 @@ bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev)
D2D1::IdentityMatrix(),
1.0,
NULL,
- D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND),
+ d->layerOptions()),
NULL);
} else {
QRect clip(0, 0, pdev->width(), pdev->height());
@@ -897,7 +1004,17 @@ bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev)
bool QWindowsDirect2DPaintEngine::end()
{
Q_D(QWindowsDirect2DPaintEngine);
- // First pop any user-applied clipping
+
+ // Always clear all emulation-related things so we are in a clean state for our next painting run
+ const bool emulatingComposition = d->flags.testFlag(EmulateComposition);
+ d->flags &= ~QWindowsDirect2DPaintEngine::EmulateComposition;
+ if (!d->fallbackImage.isNull()) {
+ if (emulatingComposition)
+ drawImage(d->fallbackImage.rect(), d->fallbackImage, d->fallbackImage.rect());
+ d->fallbackImage = QImage();
+ }
+
+ // Pop any user-applied clipping
d->clearClips();
// Now the system clip from begin() above
if (d->clipFlags & SimpleSystemClip) {
@@ -906,6 +1023,7 @@ bool QWindowsDirect2DPaintEngine::end()
} else {
d->dc()->PopLayer();
}
+
return d->bitmap->deviceContext()->end();
}
@@ -1210,7 +1328,12 @@ void QWindowsDirect2DPaintEngine::drawLines(const QLine *lines, int lineCount)
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());
+ if (!d->pen.dashBrush || state()->renderHints.testFlag(QPainter::HighQualityAntialiasing)) {
+ d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
+ } else {
+ d->pen.dashBrush->SetTransform(transformFromLine(lines[i], d->pen.qpen.widthF()));
+ d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.dashBrush.Get(), d->pen.qpen.widthF(), NULL);
+ }
}
}
}
@@ -1246,7 +1369,12 @@ void QWindowsDirect2DPaintEngine::drawLines(const QLineF *lines, int lineCount)
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());
+ if (!d->pen.dashBrush || state()->renderHints.testFlag(QPainter::HighQualityAntialiasing)) {
+ d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
+ } else {
+ d->pen.dashBrush->SetTransform(transformFromLine(lines[i], d->pen.qpen.widthF()));
+ d->dc()->DrawLine(d2d_p1, d2d_p2, d->pen.dashBrush.Get(), d->pen.qpen.widthF(), NULL);
+ }
}
}
}
@@ -1335,6 +1463,19 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
return;
}
+ if (d->flags.testFlag(EmulateComposition)) {
+ const qreal points[] = {
+ r.x(), r.y(),
+ r.x() + r.width(), r.y(),
+ r.x() + r.width(), r.y() + r.height(),
+ r.x(), r.y() + r.height()
+ };
+ const QVectorPath vp(points, 4, 0, QVectorPath::RectangleHint);
+ const QBrush brush(sr.isValid() ? pm.copy(sr.toRect()) : pm);
+ rasterFill(vp, brush);
+ return;
+ }
+
QWindowsDirect2DPlatformPixmap *pp = static_cast<QWindowsDirect2DPlatformPixmap *>(pm.handle());
QWindowsDirect2DBitmap *bitmap = pp->bitmap();
@@ -1411,7 +1552,7 @@ void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticText
return;
}
- ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(staticTextItem->font, staticTextItem->fontEngine());
+ ComPtr<IDWriteFontFace> fontFace = d->fontFaceFromFontEngine(staticTextItem->fontEngine());
if (!fontFace) {
qWarning("%s: Could not find font - falling back to slow text rendering path.", __FUNCTION__);
QPaintEngineEx::drawStaticTextItem(staticTextItem);
@@ -1432,14 +1573,14 @@ void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticText
glyphOffsets[i].ascenderOffset = staticTextItem->glyphPositions[i].y.toReal() * -1;
}
- drawGlyphRun(D2D1::Point2F(0, 0),
- fontFace.Get(),
- staticTextItem->font,
- staticTextItem->numGlyphs,
- glyphIndices.constData(),
- glyphAdvances.constData(),
- glyphOffsets.constData(),
- false);
+ d->drawGlyphRun(D2D1::Point2F(0, 0),
+ fontFace.Get(),
+ staticTextItem->fontEngine()->fontDef,
+ staticTextItem->numGlyphs,
+ glyphIndices.constData(),
+ glyphAdvances.constData(),
+ glyphOffsets.constData(),
+ false);
}
void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
@@ -1459,7 +1600,7 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem
return;
}
- ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(*ti.f, ti.fontEngine);
+ ComPtr<IDWriteFontFace> fontFace = d->fontFaceFromFontEngine(ti.fontEngine);
if (!fontFace) {
qWarning("%s: Could not find font - falling back to slow text rendering path.", __FUNCTION__);
QPaintEngine::drawTextItem(p, textItem);
@@ -1482,72 +1623,14 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem
const bool rtl = (ti.flags & QTextItem::RightToLeft);
const QPointF offset(rtl ? ti.width.toReal() : 0, 0);
- drawGlyphRun(to_d2d_point_2f(p + offset),
- fontFace.Get(),
- ti.font(),
- ti.glyphs.numGlyphs,
- glyphIndices.constData(),
- glyphAdvances.constData(),
- glyphOffsets.constData(),
- rtl);
-}
-
-inline static FLOAT pointSizeToDIP(qreal pointSize, FLOAT dpiY)
-{
- return (pointSize + (pointSize / qreal(3.0))) * (dpiY / 96.0f);
-}
-
-inline static FLOAT pixelSizeToDIP(int pixelSize, FLOAT dpiY)
-{
- return FLOAT(pixelSize) * 96.0f / dpiY;
-}
-
-inline static FLOAT fontSizeInDIP(const QFont &font)
-{
- FLOAT dpiX, dpiY;
- QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&dpiX, &dpiY);
-
- if (font.pixelSize() == -1) {
- // font size was set as points
- return pointSizeToDIP(font.pointSizeF(), dpiY);
- } else {
- // font size was set as pixels
- return pixelSizeToDIP(font.pixelSize(), dpiY);
- }
-}
-
-void QWindowsDirect2DPaintEngine::drawGlyphRun(const D2D1_POINT_2F &pos,
- IDWriteFontFace *fontFace,
- const QFont &font,
- int numGlyphs,
- const UINT16 *glyphIndices,
- const FLOAT *glyphAdvances,
- const DWRITE_GLYPH_OFFSET *glyphOffsets,
- bool rtl)
-{
- Q_D(QWindowsDirect2DPaintEngine);
-
- DWRITE_GLYPH_RUN glyphRun = {
- fontFace, // IDWriteFontFace *fontFace;
- fontSizeInDIP(font), // FLOAT fontEmSize;
- numGlyphs, // UINT32 glyphCount;
- glyphIndices, // const UINT16 *glyphIndices;
- glyphAdvances, // const FLOAT *glyphAdvances;
- glyphOffsets, // const DWRITE_GLYPH_OFFSET *glyphOffsets;
- FALSE, // BOOL isSideways;
- rtl ? 1 : 0 // UINT32 bidiLevel;
- };
-
- const bool antiAlias = bool((state()->renderHints & QPainter::TextAntialiasing)
- && !(font.styleStrategy() & QFont::NoAntialias));
- d->dc()->SetTextAntialiasMode(antiAlias ? D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE
- : D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
-
- d->dc()->DrawGlyphRun(pos,
- &glyphRun,
- NULL,
- d->pen.brush.Get(),
- DWRITE_MEASURING_MODE_GDI_CLASSIC);
+ d->drawGlyphRun(to_d2d_point_2f(p + offset),
+ fontFace.Get(),
+ ti.fontEngine->fontDef,
+ ti.glyphs.numGlyphs,
+ glyphIndices.constData(),
+ glyphAdvances.constData(),
+ glyphOffsets.constData(),
+ rtl);
}
void QWindowsDirect2DPaintEngine::ensureBrush()
@@ -1576,9 +1659,17 @@ void QWindowsDirect2DPaintEngine::rasterFill(const QVectorPath &path, const QBru
{
Q_D(QWindowsDirect2DPaintEngine);
- QImage img(d->bitmap->size(), QImage::Format_ARGB32);
- img.fill(Qt::transparent);
+ if (d->fallbackImage.isNull()) {
+ if (d->flags.testFlag(EmulateComposition)) {
+ QWindowsDirect2DPaintEngineSuspender suspender(this);
+ d->fallbackImage = d->bitmap->toImage();
+ } else {
+ d->fallbackImage = QImage(d->bitmap->size(), QImage::Format_ARGB32_Premultiplied);
+ d->fallbackImage.fill(Qt::transparent);
+ }
+ }
+ QImage &img = d->fallbackImage;
QPainter p;
QPaintEngine *engine = img.paintEngine();
@@ -1625,11 +1716,14 @@ void QWindowsDirect2DPaintEngine::rasterFill(const QVectorPath &path, const QBru
if (!p.end())
qWarning("%s: Paint Engine end returned false", __FUNCTION__);
- d->updateClipEnabled(false);
- d->updateTransform(QTransform());
- drawImage(img.rect(), img, img.rect());
- transformChanged();
- clipEnabledChanged();
+ if (!d->flags.testFlag(EmulateComposition)) { // Emulated fallback will be flattened in end()
+ d->updateClipEnabled(false);
+ d->updateTransform(QTransform());
+ drawImage(img.rect(), img, img.rect());
+ d->fallbackImage = QImage();
+ transformChanged();
+ clipEnabledChanged();
+ }
} else {
qWarning("%s: Could not fall back to QImage", __FUNCTION__);
}
@@ -1639,6 +1733,9 @@ bool QWindowsDirect2DPaintEngine::emulationRequired(EmulationType type) const
{
Q_D(const QWindowsDirect2DPaintEngine);
+ if (d->flags.testFlag(EmulateComposition))
+ return true;
+
if (!state()->matrix.isAffine())
return true;
@@ -1678,49 +1775,71 @@ void QWindowsDirect2DPaintEngine::adjustForAliasing(QPointF *point)
(*point) += adjustment;
}
-Microsoft::WRL::ComPtr<IDWriteFontFace> QWindowsDirect2DPaintEngine::fontFaceFromFontEngine(const QFont &font, QFontEngine *fe)
+void QWindowsDirect2DPaintEngine::suspend()
{
- Q_D(QWindowsDirect2DPaintEngine);
+ end();
+}
- ComPtr<IDWriteFontFace> fontFace = d->fontCache.value(font);
- if (fontFace)
- return fontFace;
+void QWindowsDirect2DPaintEngine::resume()
+{
+ begin(paintDevice());
+ clipEnabledChanged();
+ penChanged();
+ brushChanged();
+ brushOriginChanged();
+ opacityChanged();
+ compositionModeChanged();
+ renderHintsChanged();
+ transformChanged();
+}
- switch (fe->type()) {
- case QFontEngine::Win:
+class QWindowsDirect2DPaintEngineSuspenderImpl
+{
+ Q_DISABLE_COPY(QWindowsDirect2DPaintEngineSuspenderImpl)
+ QWindowsDirect2DPaintEngine *m_engine;
+ bool m_active;
+public:
+ QWindowsDirect2DPaintEngineSuspenderImpl(QWindowsDirect2DPaintEngine *engine)
+ : m_engine(engine)
+ , m_active(engine->isActive())
{
- QWindowsFontEngine *wfe = static_cast<QWindowsFontEngine *>(fe);
- QSharedPointer<QWindowsFontEngineData> wfed = wfe->fontEngineData();
-
- HGDIOBJ oldfont = wfe->selectDesignFont();
- HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFaceFromHdc(wfed->hdc, &fontFace);
- DeleteObject(SelectObject(wfed->hdc, oldfont));
- if (FAILED(hr))
- qWarning("%s: Could not create DirectWrite fontface from HDC: %#x", __FUNCTION__, hr);
-
+ if (m_active)
+ m_engine->suspend();
}
- break;
-#ifndef QT_NO_DIRECTWRITE
+ ~QWindowsDirect2DPaintEngineSuspenderImpl()
+ {
+ if (m_active)
+ m_engine->resume();
+ }
+};
- case QFontEngine::DirectWrite:
+class QWindowsDirect2DPaintEngineSuspenderPrivate
+{
+public:
+ QWindowsDirect2DPaintEngineSuspenderPrivate(QWindowsDirect2DPaintEngine *engine)
+ : engineSuspender(engine)
+ , dcSuspender(static_cast<QWindowsDirect2DPaintEnginePrivate *>(engine->d_ptr.data())->bitmap->deviceContext())
{
- QWindowsFontEngineDirectWrite *wfedw = static_cast<QWindowsFontEngineDirectWrite *>(fe);
- fontFace = wfedw->directWriteFontFace();
}
- break;
-#endif // QT_NO_DIRECTWRITE
+ QWindowsDirect2DPaintEngineSuspenderImpl engineSuspender;
+ QWindowsDirect2DDeviceContextSuspender dcSuspender;
+};
- default:
- qWarning("%s: Unknown font engine!", __FUNCTION__);
- break;
- }
+QWindowsDirect2DPaintEngineSuspender::QWindowsDirect2DPaintEngineSuspender(QWindowsDirect2DPaintEngine *engine)
+ : d_ptr(new QWindowsDirect2DPaintEngineSuspenderPrivate(engine))
+{
+
+}
- if (fontFace)
- d->fontCache.insert(font, fontFace);
+QWindowsDirect2DPaintEngineSuspender::~QWindowsDirect2DPaintEngineSuspender()
+{
+}
- return fontFace;
+void QWindowsDirect2DPaintEngineSuspender::resume()
+{
+ d_ptr.reset();
}
QT_END_NAMESPACE