summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLouai Al-Khanji <louai.al-khanji@digia.com>2013-12-04 13:40:23 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-10 15:10:29 +0100
commitb9362903b339e57362a7a3296904504521d0e26f (patch)
treeea5f735c17d958fa00f7cf46e40e86be10ed0e26
parent5a2fc4c367d4645ae3350fdcfb6c1bbd0e9c1a97 (diff)
Add new direct2d platform plugin
This is an alternative plugin for the windows platform. It shares most code with the current windows plugin, but substitutes a direct2d-based paint engine for window backing stores and pixmaps. Change-Id: I78fafd9c5871fa090b49436f5b40ec80f8789f8b Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
-rw-r--r--config.tests/qpa/direct2d/direct2d.cpp57
-rw-r--r--config.tests/qpa/direct2d/direct2d.pro4
-rw-r--r--src/gui/image/qplatformpixmap.h3
-rw-r--r--src/gui/painting/qpaintengine.cpp1
-rw-r--r--src/gui/painting/qpaintengine.h1
-rw-r--r--src/plugins/platforms/direct2d/direct2d.json3
-rw-r--r--src/plugins/platforms/direct2d/direct2d.pro39
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp239
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h76
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp205
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h81
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp218
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h84
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp135
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h95
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h96
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp122
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h78
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp64
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h58
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp131
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h71
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp1116
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h87
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp179
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h85
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp66
-rw-r--r--src/plugins/platforms/platforms.pro4
-rw-r--r--tools/configure/configureapp.cpp29
29 files changed, 3426 insertions, 1 deletions
diff --git a/config.tests/qpa/direct2d/direct2d.cpp b/config.tests/qpa/direct2d/direct2d.cpp
new file mode 100644
index 0000000000..66966ae385
--- /dev/null
+++ b/config.tests/qpa/direct2d/direct2d.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include <d3d11_1.h>
+#include <d2d1_1.h>
+#include <d2d1_1helper.h>
+#include <dxgi1_2.h>
+#include <wrl.h>
+#include <dwrite.h>
+
+using Microsoft::WRL::ComPtr;
+
+int main(int, char**)
+{
+ ComPtr<ID2D1Factory1> d2dFactory;
+ D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, d2dFactory.ReleaseAndGetAddressOf());
+
+ return 0;
+}
diff --git a/config.tests/qpa/direct2d/direct2d.pro b/config.tests/qpa/direct2d/direct2d.pro
new file mode 100644
index 0000000000..ab62a1da5c
--- /dev/null
+++ b/config.tests/qpa/direct2d/direct2d.pro
@@ -0,0 +1,4 @@
+SOURCES = direct2d.cpp
+LIBS += -ld2d1 -ldwrite -ld3d11
+CONFIG -= qt
+CONFIG += console
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index 81125bdec4..435811eb84 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -69,7 +69,8 @@ public:
};
enum ClassId { RasterClass, DirectFBClass,
- BlitterClass, CustomClass = 1024 };
+ BlitterClass, Direct2DClass,
+ CustomClass = 1024 };
QPlatformPixmap(PixelType pixelType, int classId);
virtual ~QPlatformPixmap();
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index f1eaea0f6b..acab08e794 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -387,6 +387,7 @@ void QPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDraw
\value OpenGL2
\value PaintBuffer
\value Blitter
+ \value Direct2D Windows only, Direct2D based engine
*/
/*!
diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h
index 18b6d84146..7b928ba5f6 100644
--- a/src/gui/painting/qpaintengine.h
+++ b/src/gui/painting/qpaintengine.h
@@ -207,6 +207,7 @@ public:
OpenGL2,
PaintBuffer,
Blitter,
+ Direct2D,
User = 50, // first user type id
MaxUser = 100 // last user type id
diff --git a/src/plugins/platforms/direct2d/direct2d.json b/src/plugins/platforms/direct2d/direct2d.json
new file mode 100644
index 0000000000..aaea92f0ef
--- /dev/null
+++ b/src/plugins/platforms/direct2d/direct2d.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "direct2d" ]
+}
diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro
new file mode 100644
index 0000000000..5a1e71b962
--- /dev/null
+++ b/src/plugins/platforms/direct2d/direct2d.pro
@@ -0,0 +1,39 @@
+TARGET = qdirect2d
+
+PLUGIN_TYPE = platforms
+PLUGIN_CLASS_NAME = QWindowsDirect2DIntegrationPlugin
+load(qt_plugin)
+
+QT *= core-private
+QT *= gui-private
+QT *= platformsupport-private
+
+LIBS *= -ld2d1 -ld3d11 -ldwrite
+
+include(../windows/windows.pri)
+
+SOURCES += \
+ qwindowsdirect2dpaintengine.cpp \
+ qwindowsdirect2dpaintdevice.cpp \
+ qwindowsdirect2dplatformpixmap.cpp \
+ qwindowsdirect2dcontext.cpp \
+ qwindowsdirect2dbitmap.cpp \
+ qwindowsdirect2dbackingstore.cpp \
+ qwindowsdirect2dintegration.cpp \
+ qwindowsdirect2dplatformplugin.cpp \
+ qwindowsdirect2ddevicecontext.cpp \
+ qwindowsdirect2dnativeinterface.cpp
+
+HEADERS += \
+ qwindowsdirect2dpaintengine.h \
+ qwindowsdirect2dpaintdevice.h \
+ qwindowsdirect2dplatformpixmap.h \
+ qwindowsdirect2dcontext.h \
+ qwindowsdirect2dhelpers.h \
+ qwindowsdirect2dbitmap.h \
+ qwindowsdirect2dbackingstore.h \
+ qwindowsdirect2dintegration.h \
+ qwindowsdirect2ddevicecontext.h \
+ qwindowsdirect2dnativeinterface.h
+
+OTHER_FILES += direct2d.json
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
new file mode 100644
index 0000000000..379e75c26e
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dbackingstore.h"
+#include "qwindowsdirect2dintegration.h"
+#include "qwindowsdirect2dcontext.h"
+#include "qwindowsdirect2dpaintdevice.h"
+#include "qwindowsdirect2dbitmap.h"
+#include "qwindowsdirect2ddevicecontext.h"
+
+#include "qwindowswindow.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QWindow>
+#include <QtCore/QDebug>
+
+#include <dxgi1_2.h>
+#include <d3d11.h>
+#include <wrl.h>
+
+using Microsoft::WRL::ComPtr;
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DBackingStorePrivate
+{
+public:
+ QWindowsDirect2DBackingStorePrivate() {}
+
+ ComPtr<IDXGISwapChain1> swapChain;
+ QSharedPointer<QWindowsDirect2DBitmap> backingStore;
+ QScopedPointer<QWindowsDirect2DPaintDevice> nativePaintDevice;
+
+ bool init(HWND hwnd)
+ {
+ DXGI_SWAP_CHAIN_DESC1 desc = {};
+
+ desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ desc.SampleDesc.Count = 1;
+ desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ desc.BufferCount = 1;
+ desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
+
+ HRESULT hr = QWindowsDirect2DContext::instance()->dxgiFactory()->CreateSwapChainForHwnd(
+ QWindowsDirect2DContext::instance()->d3dDevice(), // [in] IUnknown *pDevice
+ hwnd, // [in] HWND hWnd
+ &desc, // [in] const DXGI_SWAP_CHAIN_DESC1 *pDesc
+ NULL, // [in] const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc
+ NULL, // [in] IDXGIOutput *pRestrictToOutput
+ swapChain.ReleaseAndGetAddressOf()); // [out] IDXGISwapChain1 **ppSwapChain
+
+ if (FAILED(hr))
+ qWarning("%s: Could not create swap chain: %#x", __FUNCTION__, hr);
+
+ return SUCCEEDED(hr);
+ }
+
+ bool setupPaintDevice()
+ {
+ if (!backingStore) {
+ ComPtr<ID2D1DeviceContext> deviceContext;
+ ComPtr<IDXGISurface1> backBufferSurface;
+ ComPtr<ID2D1Bitmap1> backBufferBitmap;
+
+ HRESULT hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext(
+ D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
+ deviceContext.ReleaseAndGetAddressOf());
+ if (FAILED(hr)) {
+ qWarning("%s: Couldn't create Direct2D Device context: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ hr = swapChain->GetBuffer(0, IID_PPV_ARGS(&backBufferSurface));
+ if (FAILED(hr)) {
+ qWarning("%s: Could not query backbuffer for DXGI Surface: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ hr = deviceContext->CreateBitmapFromDxgiSurface(backBufferSurface.Get(), NULL, backBufferBitmap.ReleaseAndGetAddressOf());
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create Direct2D Bitmap from DXGI Surface: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ backingStore.reset(new QWindowsDirect2DBitmap(backBufferBitmap.Get(), deviceContext.Get()));
+ }
+
+ if (!nativePaintDevice)
+ nativePaintDevice.reset(new QWindowsDirect2DPaintDevice(backingStore.data(), QInternal::Widget));
+
+ return true;
+ }
+
+ void releaseBackingStore()
+ {
+ nativePaintDevice.reset();
+ backingStore.reset();
+ }
+
+ QPaintDevice *paintDevice()
+ {
+ setupPaintDevice();
+ return nativePaintDevice.data();
+ }
+
+ void flush()
+ {
+ swapChain->Present(1, 0);
+ }
+};
+
+/*!
+ \class QWindowsDirect2DBackingStore
+ \brief Backing store for windows.
+ \internal
+ \ingroup qt-lighthouse-win
+*/
+
+QWindowsDirect2DBackingStore::QWindowsDirect2DBackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
+ , d_ptr(new QWindowsDirect2DBackingStorePrivate)
+{
+}
+
+bool QWindowsDirect2DBackingStore::init()
+{
+ if (window()->surfaceType() == QSurface::RasterSurface) {
+ Q_D(QWindowsDirect2DBackingStore);
+ return d->init(windowsWindow()->handle());
+ }
+
+ return true;
+}
+
+QWindowsDirect2DBackingStore *QWindowsDirect2DBackingStore::create(QWindow *window)
+{
+ QWindowsDirect2DBackingStore *result = new QWindowsDirect2DBackingStore(window);
+
+ if (!result->init()) {
+ delete result;
+ result = 0;
+ }
+
+ return result;
+}
+
+QWindowsDirect2DBackingStore::~QWindowsDirect2DBackingStore()
+{
+ Q_D(QWindowsDirect2DBackingStore);
+ d->releaseBackingStore();
+ d->swapChain.Reset();
+}
+
+QPaintDevice *QWindowsDirect2DBackingStore::paintDevice()
+{
+ QPaintDevice *result = 0;
+
+ if (window()->surfaceType() == QSurface::RasterSurface) {
+ Q_D(QWindowsDirect2DBackingStore);
+ result = d->paintDevice();
+ }
+
+ return result;
+}
+
+void QWindowsDirect2DBackingStore::flush(QWindow *, const QRegion &, const QPoint &)
+{
+ if (window()->surfaceType() == QSurface::RasterSurface) {
+ Q_D(QWindowsDirect2DBackingStore);
+ d->flush();
+ }
+}
+
+void QWindowsDirect2DBackingStore::resize(const QSize &size, const QRegion &region)
+{
+ Q_UNUSED(region);
+
+ if (window()->surfaceType() != QSurface::RasterSurface)
+ return;
+
+ Q_D(QWindowsDirect2DBackingStore);
+ d->releaseBackingStore();
+ QWindowsDirect2DContext::instance()->d3dDeviceContext()->ClearState();
+
+ HRESULT hr = d->swapChain->ResizeBuffers(0,
+ size.width(), size.height(),
+ DXGI_FORMAT_UNKNOWN,
+ 0);
+ if (FAILED(hr))
+ qWarning("%s: Could not resize buffers: %#x", __FUNCTION__, hr);
+}
+
+QWindowsWindow *QWindowsDirect2DBackingStore::windowsWindow() const
+{
+ if (const QWindow *w = window())
+ if (QPlatformWindow *pw = w->handle())
+ return static_cast<QWindowsWindow *>(pw);
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
new file mode 100644
index 0000000000..89ecee67dd
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DBACKINGSTORE_H
+#define QWINDOWSDIRECT2DBACKINGSTORE_H
+
+#include <QtCore/QScopedPointer>
+#include <QtGui/qpa/qplatformbackingstore.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsWindow;
+class QWindowsDirect2DBackingStorePrivate;
+
+class QWindowsDirect2DBackingStore : public QPlatformBackingStore
+{
+ Q_DECLARE_PRIVATE(QWindowsDirect2DBackingStore)
+ Q_DISABLE_COPY(QWindowsDirect2DBackingStore)
+
+public:
+ static QWindowsDirect2DBackingStore *create(QWindow *window);
+ ~QWindowsDirect2DBackingStore();
+
+ QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
+ void flush(QWindow *, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
+ void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
+
+private:
+ QWindowsDirect2DBackingStore(QWindow *window);
+ bool init();
+
+ QWindowsWindow *windowsWindow() const;
+ QScopedPointer<QWindowsDirect2DBackingStorePrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DBACKINGSTORE_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp
new file mode 100644
index 0000000000..85c56bc73e
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dbitmap.h"
+#include "qwindowsdirect2dcontext.h"
+#include "qwindowsdirect2dhelpers.h"
+#include "qwindowsdirect2ddevicecontext.h"
+
+#include <QtGui/QImage>
+#include <QtGui/QColor>
+
+#include <wrl.h>
+
+using Microsoft::WRL::ComPtr;
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DBitmapPrivate
+{
+public:
+ QWindowsDirect2DBitmapPrivate(ID2D1DeviceContext *dc = 0, ID2D1Bitmap1 *bm = 0)
+ : bitmap(bm)
+ , deviceContext(new QWindowsDirect2DDeviceContext(dc))
+ {
+ deviceContext->get()->SetTarget(bm);
+ }
+
+ D2D1_BITMAP_PROPERTIES1 bitmapProperties() const
+ {
+ FLOAT dpiX, dpiY;
+ QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&dpiX, &dpiY);
+
+ return D2D1::BitmapProperties1(
+ D2D1_BITMAP_OPTIONS_TARGET,
+ D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_PREMULTIPLIED),
+ dpiX, dpiY);
+
+ }
+
+ bool resize(int width, int height, const void *data = 0, int pitch = 0)
+ {
+ deviceContext->get()->SetTarget(0);
+ bitmap.Reset();
+
+ D2D1_SIZE_U size = {
+ width, height
+ };
+
+ HRESULT hr = deviceContext->get()->CreateBitmap(size, data, pitch,
+ bitmapProperties(),
+ bitmap.ReleaseAndGetAddressOf());
+ if (SUCCEEDED(hr))
+ deviceContext->get()->SetTarget(bitmap.Get());
+ else
+ qWarning("%s: Could not create bitmap: %#x", __FUNCTION__, hr);
+
+ return SUCCEEDED(hr);
+ }
+
+ QImage toImage(const QRect &rect)
+ {
+ if (!bitmap)
+ return QImage();
+
+ ComPtr<ID2D1Bitmap1> mappingCopy;
+
+ HRESULT hr = S_OK;
+ D2D1_SIZE_U size = bitmap->GetPixelSize();
+
+ D2D1_BITMAP_PROPERTIES1 properties = bitmapProperties();
+ properties.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ;
+
+ hr = deviceContext->get()->CreateBitmap(size, NULL, NULL,
+ properties, &mappingCopy);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create bitmap: %#x", __FUNCTION__, hr);
+ return QImage();
+ }
+
+ hr = mappingCopy->CopyFromBitmap(NULL, bitmap.Get(), NULL);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not copy from bitmap: %#x", __FUNCTION__, hr);
+ return QImage();
+ }
+
+ D2D1_MAPPED_RECT mappedRect;
+ hr = mappingCopy->Map(D2D1_MAP_OPTIONS_READ, &mappedRect);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not map: %#x", __FUNCTION__, hr);
+ return QImage();
+ }
+
+ return QImage(static_cast<const uchar *>(mappedRect.bits),
+ size.width, size.height, mappedRect.pitch,
+ QImage::Format_ARGB32_Premultiplied).copy(rect);
+ }
+
+ QScopedPointer<QWindowsDirect2DDeviceContext> deviceContext;
+ ComPtr<ID2D1Bitmap1> bitmap;
+};
+
+QWindowsDirect2DBitmap::QWindowsDirect2DBitmap()
+ : d_ptr(new QWindowsDirect2DBitmapPrivate)
+{
+}
+
+QWindowsDirect2DBitmap::QWindowsDirect2DBitmap(ID2D1Bitmap1 *bitmap, ID2D1DeviceContext *dc)
+ : d_ptr(new QWindowsDirect2DBitmapPrivate(dc, bitmap))
+{
+}
+
+QWindowsDirect2DBitmap::~QWindowsDirect2DBitmap()
+{
+}
+
+bool QWindowsDirect2DBitmap::resize(int width, int height)
+{
+ Q_D(QWindowsDirect2DBitmap);
+ return d->resize(width, height);
+}
+
+bool QWindowsDirect2DBitmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
+{
+ Q_D(QWindowsDirect2DBitmap);
+
+ QImage converted = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
+ return d->resize(converted.width(), converted.height(),
+ converted.constBits(), converted.bytesPerLine());
+}
+
+ID2D1Bitmap1* QWindowsDirect2DBitmap::bitmap() const
+{
+ Q_D(const QWindowsDirect2DBitmap);
+ return d->bitmap.Get();
+}
+
+QWindowsDirect2DDeviceContext *QWindowsDirect2DBitmap::deviceContext() const
+{
+ Q_D(const QWindowsDirect2DBitmap);
+ return d->deviceContext.data();
+}
+
+void QWindowsDirect2DBitmap::fill(const QColor &color)
+{
+ Q_D(QWindowsDirect2DBitmap);
+
+ d->deviceContext->begin();
+ d->deviceContext->get()->Clear(to_d2d_color_f(color));
+ d->deviceContext->end();
+}
+
+QImage QWindowsDirect2DBitmap::toImage(const QRect &rect)
+{
+ Q_D(QWindowsDirect2DBitmap);
+ return d->toImage(rect);
+}
+
+QSize QWindowsDirect2DBitmap::size() const
+{
+ Q_D(const QWindowsDirect2DBitmap);
+
+ D2D1_SIZE_U size = d->bitmap->GetPixelSize();
+ return QSize(size.width, size.height);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h
new file mode 100644
index 0000000000..d7015ef342
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DBITMAP_H
+#define QWINDOWSDIRECT2DBITMAP_H
+
+#include <QtCore/QScopedPointer>
+#include <QtGui/QImage>
+
+struct ID2D1DeviceContext;
+struct ID2D1Bitmap1;
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DDeviceContext;
+class QWindowsDirect2DBitmapPrivate;
+class QWindowsDirect2DBitmap
+{
+ Q_DECLARE_PRIVATE(QWindowsDirect2DBitmap)
+ Q_DISABLE_COPY(QWindowsDirect2DBitmap)
+public:
+ QWindowsDirect2DBitmap();
+ QWindowsDirect2DBitmap(ID2D1Bitmap1 *bitmap, ID2D1DeviceContext *dc);
+ ~QWindowsDirect2DBitmap();
+
+ bool resize(int width, int height);
+ bool fromImage(const QImage &image, Qt::ImageConversionFlags flags);
+
+ ID2D1Bitmap1* bitmap() const;
+ QWindowsDirect2DDeviceContext* deviceContext() const;
+
+ void fill(const QColor &color);
+ QImage toImage(const QRect &rect = QRect());
+
+ QSize size() const;
+
+private:
+ QScopedPointer<QWindowsDirect2DBitmapPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DBITMAP_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
new file mode 100644
index 0000000000..58002fb0dd
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dcontext.h"
+#include "qwindowsdirect2dhelpers.h"
+#include "qwindowsdirect2dintegration.h"
+
+#include <d3d11_1.h>
+#include <d2d1_1.h>
+#include <d2d1_1helper.h>
+#include <dxgi1_2.h>
+#include <wrl.h>
+#include <dwrite.h>
+
+using Microsoft::WRL::ComPtr;
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DContextPrivate
+{
+public:
+ bool init()
+ {
+ HRESULT hr;
+
+ D3D_FEATURE_LEVEL level;
+
+ D3D_DRIVER_TYPE typeAttempts[] = {
+ D3D_DRIVER_TYPE_HARDWARE,
+ D3D_DRIVER_TYPE_WARP
+ };
+ const int ntypes = int(sizeof(typeAttempts) / sizeof(typeAttempts[0]));
+
+ for (int i = 0; i < ntypes; i++) {
+ hr = D3D11CreateDevice(NULL,
+ typeAttempts[i],
+ NULL,
+ D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+ NULL,
+ 0,
+ D3D11_SDK_VERSION,
+ &d3dDevice,
+ &level,
+ &d3dDeviceContext);
+
+ if (SUCCEEDED(hr))
+ break;
+ }
+
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create Direct3D Device: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ ComPtr<IDXGIDevice> dxgiDevice;
+ ComPtr<IDXGIAdapter> dxgiAdapter;
+
+ hr = d3dDevice.As(&dxgiDevice);
+ if (FAILED(hr)) {
+ qWarning("%s: DXGI Device interface query failed on D3D Device: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ hr = dxgiDevice->GetParent(IID_PPV_ARGS(&dxgiAdapter));
+ if (FAILED(hr)) {
+ qWarning("%s: Failed to probe DXGI Device for parent DXGI Adapter: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ hr = dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory));
+ if (FAILED(hr)) {
+ qWarning("%s: Failed to probe DXGI Adapter for parent DXGI Factory: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ D2D1_FACTORY_OPTIONS options = {};
+
+#ifdef QT_D2D_DEBUG_OUTPUT
+ qDebug("Turning on Direct2D debugging messages");
+ options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
+#endif // QT_D2D_DEBUG_OUTPUT
+
+ hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, options, d2dFactory.GetAddressOf());
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create Direct2D Factory: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ hr = d2dFactory->CreateDevice(dxgiDevice.Get(), &d2dDevice);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create D2D Device: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
+ static_cast<IUnknown **>(&directWriteFactory));
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create DirectWrite factory: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ hr = directWriteFactory->GetGdiInterop(&directWriteGdiInterop);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create DirectWrite GDI Interop: %#x", __FUNCTION__, hr);
+ return false;
+ }
+
+ return true;
+ }
+
+ ComPtr<ID3D11Device> d3dDevice;
+ ComPtr<ID2D1Factory1> d2dFactory;
+ ComPtr<ID2D1Device> d2dDevice;
+ ComPtr<IDXGIFactory2> dxgiFactory;
+ ComPtr<ID3D11DeviceContext> d3dDeviceContext;
+ ComPtr<IDWriteFactory> directWriteFactory;
+ ComPtr<IDWriteGdiInterop> directWriteGdiInterop;
+};
+
+QWindowsDirect2DContext::QWindowsDirect2DContext()
+ : d_ptr(new QWindowsDirect2DContextPrivate)
+{
+}
+
+QWindowsDirect2DContext::~QWindowsDirect2DContext() {}
+
+bool QWindowsDirect2DContext::init()
+{
+ Q_D(QWindowsDirect2DContext);
+ return d->init();
+}
+
+QWindowsDirect2DContext *QWindowsDirect2DContext::instance()
+{
+ return QWindowsDirect2DIntegration::instance()->direct2DContext();
+}
+
+ID3D11Device *QWindowsDirect2DContext::d3dDevice() const
+{
+ Q_D(const QWindowsDirect2DContext);
+ return d->d3dDevice.Get();
+}
+
+ID2D1Device *QWindowsDirect2DContext::d2dDevice() const
+{
+ Q_D(const QWindowsDirect2DContext);
+ return d->d2dDevice.Get();
+}
+
+ID2D1Factory1 *QWindowsDirect2DContext::d2dFactory() const
+{
+ Q_D(const QWindowsDirect2DContext);
+ return d->d2dFactory.Get();
+}
+
+IDXGIFactory2 *QWindowsDirect2DContext::dxgiFactory() const
+{
+ Q_D(const QWindowsDirect2DContext);
+ return d->dxgiFactory.Get();
+}
+
+ID3D11DeviceContext *QWindowsDirect2DContext::d3dDeviceContext() const
+{
+ Q_D(const QWindowsDirect2DContext);
+ return d->d3dDeviceContext.Get();
+}
+
+IDWriteFactory *QWindowsDirect2DContext::dwriteFactory() const
+{
+ Q_D(const QWindowsDirect2DContext);
+ return d->directWriteFactory.Get();
+}
+
+IDWriteGdiInterop *QWindowsDirect2DContext::dwriteGdiInterop() const
+{
+ Q_D(const QWindowsDirect2DContext);
+ return d->directWriteGdiInterop.Get();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h
new file mode 100644
index 0000000000..0025463dd5
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DCONTEXT_H
+#define QWINDOWSDIRECT2DCONTEXT_H
+
+#include <QtCore/QScopedPointer>
+
+struct ID3D11Device;
+struct ID2D1Device;
+struct ID2D1Factory1;
+struct IDXGIFactory2;
+struct ID3D11DeviceContext;
+struct IDWriteFactory;
+struct IDWriteGdiInterop;
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DContextPrivate;
+class QWindowsDirect2DContext
+{
+ Q_DECLARE_PRIVATE( QWindowsDirect2DContext )
+
+public:
+ QWindowsDirect2DContext();
+ virtual ~QWindowsDirect2DContext();
+
+ bool init();
+
+ static QWindowsDirect2DContext *instance();
+
+ ID3D11Device *d3dDevice() const;
+ ID2D1Device *d2dDevice() const;
+ ID2D1Factory1 *d2dFactory() const;
+ IDXGIFactory2 *dxgiFactory() const;
+ ID3D11DeviceContext *d3dDeviceContext() const;
+ IDWriteFactory *dwriteFactory() const;
+ IDWriteGdiInterop *dwriteGdiInterop() const;
+
+private:
+ QScopedPointer<QWindowsDirect2DContextPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DCONTEXT_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp
new file mode 100644
index 0000000000..3ff4c9e636
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dcontext.h"
+#include "qwindowsdirect2dhelpers.h"
+#include "qwindowsdirect2ddevicecontext.h"
+
+#include <wrl.h>
+
+using Microsoft::WRL::ComPtr;
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DDeviceContextPrivate {
+public:
+ QWindowsDirect2DDeviceContextPrivate(ID2D1DeviceContext *dc)
+ : deviceContext(dc)
+ , refCount(0)
+ {
+ if (!dc) {
+ HRESULT hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext(
+ D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
+ &deviceContext);
+ if (FAILED(hr))
+ qFatal("%s: Couldn't create Direct2D Device Context: %#x", __FUNCTION__, hr);
+ }
+
+ Q_ASSERT(deviceContext);
+ }
+
+ void begin()
+ {
+ Q_ASSERT(deviceContext);
+ Q_ASSERT(refCount >= 0);
+
+ if (refCount == 0)
+ deviceContext->BeginDraw();
+
+ refCount++;
+ }
+
+ bool end()
+ {
+ Q_ASSERT(deviceContext);
+ Q_ASSERT(refCount >= 0);
+
+ bool success = true;
+ refCount--;
+
+ if (refCount == 0) {
+ D2D1_TAG tag1, tag2;
+ HRESULT hr = deviceContext->EndDraw(&tag1, &tag2);
+
+ if (FAILED(hr)) {
+ success = false;
+ qWarning("%s: EndDraw failed: %#x, tag1: %lld, tag2: %lld", __FUNCTION__, hr, tag1, tag2);
+ }
+ }
+
+ return success;
+ }
+
+ ComPtr<ID2D1DeviceContext> deviceContext;
+ int refCount;
+};
+
+QWindowsDirect2DDeviceContext::QWindowsDirect2DDeviceContext(ID2D1DeviceContext *dc)
+ : d_ptr(new QWindowsDirect2DDeviceContextPrivate(dc))
+{
+}
+
+QWindowsDirect2DDeviceContext::~QWindowsDirect2DDeviceContext()
+{
+
+}
+
+ID2D1DeviceContext *QWindowsDirect2DDeviceContext::get() const
+{
+ Q_D(const QWindowsDirect2DDeviceContext);
+ Q_ASSERT(d->deviceContext);
+
+ return d->deviceContext.Get();
+}
+
+void QWindowsDirect2DDeviceContext::begin()
+{
+ Q_D(QWindowsDirect2DDeviceContext);
+ d->begin();
+}
+
+bool QWindowsDirect2DDeviceContext::end()
+{
+ Q_D(QWindowsDirect2DDeviceContext);
+ return d->end();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h
new file mode 100644
index 0000000000..4986efb967
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DDEVICECONTEXT_H
+#define QWINDOWSDIRECT2DDEVICECONTEXT_H
+
+#include "qwindowsdirect2dhelpers.h"
+
+#include <QtCore/QScopedPointer>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Convenience class for handling device contexts. We have to call BeginDraw
+ * before anything can happen, and EndDraw once we're done, for every frame and
+ * pretty much any kind of operation.
+ *
+ * Unfortunately, these calls cannot be interleaved, and there is no way to check
+ * what state a device context is in.
+ *
+ * The end result is that the following throws an error if we don't track it:
+ * QPixmap pmap;
+ * QPainter painter(&pmap);
+ * pmap.clear();
+ *
+ * Here BeginDraw would first be called through the paint device, then when we clear
+ * the pixmap we would have to call it again. There is no way to know what state
+ * the device context is in when performing the clear, and activating the dc is an
+ * error. Bummer.
+ *
+ * Hence we keep a reference count here and only activate/deactivate the device
+ * if the refcount is zero.
+ *
+ * In a nutshell: Do not call BeginDraw/EndDraw yourself on the device pointer, do
+ * so through the begin/end members below.
+ */
+
+class QWindowsDirect2DDeviceContextPrivate;
+class QWindowsDirect2DDeviceContext
+{
+ Q_DECLARE_PRIVATE(QWindowsDirect2DDeviceContext)
+public:
+ QWindowsDirect2DDeviceContext(ID2D1DeviceContext *dc);
+ ~QWindowsDirect2DDeviceContext();
+
+ ID2D1DeviceContext *get() const;
+
+ void begin();
+ bool end();
+
+private:
+ QScopedPointer<QWindowsDirect2DDeviceContextPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DDEVICECONTEXT_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h
new file mode 100644
index 0000000000..0ca26ca4cb
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DHELPERS_H
+#define QWINDOWSDIRECT2DHELPERS_H
+
+#include <QtCore/QRectF>
+#include <QtCore/QSizeF>
+#include <QtCore/QPointF>
+#include <QtGui/QColor>
+#include <QtGui/QTransform>
+
+#include <d2d1_1helper.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECL_CONSTEXPR inline D2D1_RECT_U to_d2d_rect_u(const QRect &qrect)
+{
+ return D2D1::RectU(qrect.left(), qrect.top(), qrect.right(), qrect.bottom());
+}
+
+Q_DECL_CONSTEXPR inline D2D1_RECT_F to_d2d_rect_f(const QRectF &qrect)
+{
+ return D2D1::RectF(qrect.left(), qrect.top(), qrect.right(), qrect.bottom());
+}
+
+Q_DECL_CONSTEXPR inline D2D1_SIZE_U to_d2d_size_u(const QSizeF &qsize)
+{
+ return D2D1::SizeU(qsize.width(), qsize.height());
+}
+
+Q_DECL_CONSTEXPR inline D2D1_SIZE_U to_d2d_size_u(const QSize &qsize)
+{
+ return D2D1::SizeU(qsize.width(), qsize.height());
+}
+
+Q_DECL_CONSTEXPR inline D2D1_POINT_2F to_d2d_point_2f(const QPointF &qpoint)
+{
+ return D2D1::Point2F(qpoint.x(), qpoint.y());
+}
+
+Q_DECL_CONSTEXPR inline D2D1::ColorF to_d2d_color_f(const QColor &c)
+{
+ return D2D1::ColorF(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+}
+
+Q_DECL_CONSTEXPR inline D2D1_MATRIX_3X2_F to_d2d_matrix_3x2_f(const QTransform &transform)
+{
+ Q_ASSERT(transform.isAffine());
+
+ return D2D1::Matrix3x2F(transform.m11(), transform.m12(),
+ transform.m21(), transform.m22(),
+ transform.m31(), transform.m32());
+}
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DHELPERS_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
new file mode 100644
index 0000000000..c2f3c05bde
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dcontext.h"
+#include "qwindowsdirect2dintegration.h"
+#include "qwindowsdirect2dbackingstore.h"
+#include "qwindowsdirect2dplatformpixmap.h"
+#include "qwindowsdirect2dnativeinterface.h"
+
+#include "qwindowscontext.h"
+
+#include <QtCore/QDebug>
+#include <QtGui/private/qpixmap_raster_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DIntegrationPrivate
+{
+public:
+ QWindowsDirect2DNativeInterface m_nativeInterface;
+ QWindowsDirect2DContext m_d2dContext;
+};
+
+QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::create(const QStringList &paramList)
+{
+ QWindowsDirect2DIntegration *integration = new QWindowsDirect2DIntegration(paramList);
+
+ if (!integration->init()) {
+ delete integration;
+ integration = 0;
+ }
+
+ return integration;
+}
+
+QWindowsDirect2DIntegration::~QWindowsDirect2DIntegration()
+{
+
+}
+
+ QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::instance()
+ {
+ return static_cast<QWindowsDirect2DIntegration *>(QWindowsIntegration::instance());
+ }
+
+ QPlatformNativeInterface *QWindowsDirect2DIntegration::nativeInterface() const
+ {
+ return &d->m_nativeInterface;
+ }
+
+QPlatformPixmap *QWindowsDirect2DIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
+{
+ switch (type) {
+ case QPlatformPixmap::BitmapType:
+ return new QRasterPlatformPixmap(type);
+ break;
+ default:
+ return new QWindowsDirect2DPlatformPixmap(type);
+ break;
+ }
+}
+
+QPlatformBackingStore *QWindowsDirect2DIntegration::createPlatformBackingStore(QWindow *window) const
+{
+ return QWindowsDirect2DBackingStore::create(window);
+}
+
+QWindowsDirect2DContext *QWindowsDirect2DIntegration::direct2DContext() const
+{
+ return &d->m_d2dContext;
+}
+
+QWindowsDirect2DIntegration::QWindowsDirect2DIntegration(const QStringList &paramList)
+ : QWindowsIntegration(paramList)
+ , d(new QWindowsDirect2DIntegrationPrivate)
+{
+}
+
+bool QWindowsDirect2DIntegration::init()
+{
+ return d->m_d2dContext.init();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
new file mode 100644
index 0000000000..12412cbc0f
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DINTEGRATION_H
+#define QWINDOWSDIRECT2DINTEGRATION_H
+
+#include "qwindowsintegration.h"
+
+#include <QtCore/QScopedPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DContext;
+class QWindowsDirect2DIntegrationPrivate;
+
+class QWindowsDirect2DIntegration : public QWindowsIntegration
+{
+public:
+ static QWindowsDirect2DIntegration *create(const QStringList &paramList);
+
+ virtual ~QWindowsDirect2DIntegration();
+
+ static QWindowsDirect2DIntegration *instance();
+
+ QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
+ QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const Q_DECL_OVERRIDE;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+
+ QWindowsDirect2DContext *direct2DContext() const;
+
+private:
+ explicit QWindowsDirect2DIntegration(const QStringList &paramList);
+ bool init();
+
+ QScopedPointer<QWindowsDirect2DIntegrationPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DINTEGRATION_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp
new file mode 100644
index 0000000000..6792d92de5
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dnativeinterface.h"
+
+#include <QtGui/QBackingStore>
+
+QT_BEGIN_NAMESPACE
+
+void *QWindowsDirect2DNativeInterface::nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs)
+{
+ if (!bs || !bs->handle()) {
+ qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
+ return 0;
+ }
+
+ // getDC is so common we don't want to print an "invalid key" line for it
+ if (resource == "getDC")
+ return 0;
+
+ qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
+ return 0;
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h b/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h
new file mode 100644
index 0000000000..ee3f7f6eed
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DNATIVEINTERFACE_H
+#define QWINDOWSDIRECT2DNATIVEINTERFACE_H
+
+#include "qwindowsnativeinterface.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DNativeInterface : public QWindowsNativeInterface
+{
+ Q_OBJECT
+public:
+ void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs) Q_DECL_OVERRIDE;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
new file mode 100644
index 0000000000..85dbaab2ce
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dpaintdevice.h"
+#include "qwindowsdirect2dpaintengine.h"
+#include "qwindowsdirect2dcontext.h"
+#include "qwindowsdirect2dhelpers.h"
+#include "qwindowsdirect2dbitmap.h"
+#include "qwindowsdirect2ddevicecontext.h"
+
+#include "qwindowswindow.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DPaintDevicePrivate
+{
+public:
+ QWindowsDirect2DPaintDevicePrivate(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags f)
+ : engine(new QWindowsDirect2DPaintEngine(bitmap))
+ , bitmap(bitmap)
+ , flags(f)
+ {}
+
+ QScopedPointer<QWindowsDirect2DPaintEngine> engine;
+ QWindowsDirect2DBitmap *bitmap;
+ QInternal::PaintDeviceFlags flags;
+};
+
+QWindowsDirect2DPaintDevice::QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags flags)
+ : d_ptr(new QWindowsDirect2DPaintDevicePrivate(bitmap, flags))
+{
+}
+
+QPaintEngine *QWindowsDirect2DPaintDevice::paintEngine() const
+{
+ Q_D(const QWindowsDirect2DPaintDevice);
+
+ return d->engine.data();
+}
+
+int QWindowsDirect2DPaintDevice::devType() const
+{
+ Q_D(const QWindowsDirect2DPaintDevice);
+
+ return d->flags;
+}
+
+int QWindowsDirect2DPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ Q_D(const QWindowsDirect2DPaintDevice);
+
+ switch (metric) {
+ case QPaintDevice::PdmWidth:
+ return d->bitmap->bitmap()->GetPixelSize().width;
+ break;
+ case QPaintDevice::PdmHeight:
+ return d->bitmap->bitmap()->GetPixelSize().height;
+ break;
+ case QPaintDevice::PdmNumColors:
+ return INT_MAX;
+ break;
+ case QPaintDevice::PdmDepth:
+ return 32;
+ break;
+ case QPaintDevice::PdmDpiX:
+ case QPaintDevice::PdmPhysicalDpiX:
+ {
+ FLOAT x, y;
+ QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&x, &y);
+ return x;
+ }
+ break;
+ case QPaintDevice::PdmDpiY:
+ case QPaintDevice::PdmPhysicalDpiY:
+ {
+ FLOAT x, y;
+ QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&x, &y);
+ return y;
+ }
+ break;
+ case QPaintDevice::PdmDevicePixelRatio:
+ return 1;
+ break;
+ case QPaintDevice::PdmWidthMM:
+ case QPaintDevice::PdmHeightMM:
+ return -1;
+ break;
+ }
+
+ return -1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
new file mode 100644
index 0000000000..c799083d84
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DPAINTDEVICE_H
+#define QWINDOWSDIRECT2DPAINTDEVICE_H
+
+#include <QtCore/QScopedPointer>
+#include <QtGui/QPaintDevice>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DBitmap;
+
+class QWindowsDirect2DPaintDevicePrivate;
+class QWindowsDirect2DPaintDevice : public QPaintDevice
+{
+ Q_DECLARE_PRIVATE(QWindowsDirect2DPaintDevice)
+
+public:
+ QWindowsDirect2DPaintDevice(QWindowsDirect2DBitmap *bitmap, QInternal::PaintDeviceFlags flags);
+ QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
+ int devType() const Q_DECL_OVERRIDE;
+
+protected:
+ int metric(PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
+
+private:
+ QScopedPointer<QWindowsDirect2DPaintDevicePrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DPAINTDEVICE_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
new file mode 100644
index 0000000000..aad3d192e7
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -0,0 +1,1116 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dpaintengine.h"
+#include "qwindowsdirect2dplatformpixmap.h"
+#include "qwindowsdirect2dpaintdevice.h"
+#include "qwindowsdirect2dcontext.h"
+#include "qwindowsdirect2dhelpers.h"
+#include "qwindowsdirect2dbitmap.h"
+#include "qwindowsdirect2ddevicecontext.h"
+
+#include "qwindowsfontengine.h"
+#include "qwindowsfontenginedirectwrite.h"
+#include "qwindowsfontdatabase.h"
+#include "qwindowsintegration.h"
+
+#include <QtCore/QStack>
+#include <QtGui/private/qpaintengine_p.h>
+#include <QtGui/private/qtextengine_p.h>
+#include <QtGui/private/qfontengine_p.h>
+
+#include <dwrite_1.h>
+#include <wrl.h>
+
+using Microsoft::WRL::ComPtr;
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ D2DDebugDrawInitialStateTag = -1,
+ D2DDebugDrawEllipseTag = 1,
+ D2DDebugDrawImageTag,
+ D2DDebugDrawLinesTag,
+ D2DDebugDrawPathTag,
+ D2DDebugDrawPixmapTag,
+ D2DDebugDrawPointsTag,
+ D2DDebugDrawPolygonTag,
+ D2DDebugDrawRectsTag,
+ D2DDebugDrawTextItemTag,
+ D2DDebugDrawTiledPixmap
+};
+#define D2D_TAG(tag) d->dc()->SetTags(tag, tag)
+
+Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
+
+static inline ID2D1Factory1 *factory()
+{
+ return QWindowsDirect2DContext::instance()->d2dFactory();
+}
+
+static const qreal defaultOpacity = 1.0;
+static const qreal defaultPenWidth = 1.0;
+
+static ComPtr<ID2D1PathGeometry> painterPathToPathGeometry(const QPainterPath &path)
+{
+ ComPtr<ID2D1PathGeometry> geometry;
+ ComPtr<ID2D1GeometrySink> sink;
+
+ HRESULT hr = factory()->CreatePathGeometry(&geometry);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create path geometry: %#x", __FUNCTION__, hr);
+ return NULL;
+ }
+
+ hr = geometry->Open(&sink);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create geometry sink: %#x", __FUNCTION__, hr);
+ return NULL;
+ }
+
+ switch (path.fillRule()) {
+ case Qt::WindingFill:
+ sink->SetFillMode(D2D1_FILL_MODE_WINDING);
+ break;
+ case Qt::OddEvenFill:
+ sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE);
+ break;
+ }
+
+ bool inFigure = false;
+
+ for (int i = 0; i < path.elementCount(); i++) {
+ const QPainterPath::Element element = path.elementAt(i);
+
+ switch (element.type) {
+ case QPainterPath::MoveToElement:
+ if (inFigure)
+ sink->EndFigure(D2D1_FIGURE_END_OPEN);
+
+ sink->BeginFigure(to_d2d_point_2f(element), D2D1_FIGURE_BEGIN_FILLED);
+ inFigure = true;
+ break;
+
+ case QPainterPath::LineToElement:
+ sink->AddLine(to_d2d_point_2f(element));
+ break;
+
+ case QPainterPath::CurveToElement:
+ {
+ const QPainterPath::Element data1 = path.elementAt(++i);
+ const QPainterPath::Element data2 = path.elementAt(++i);
+
+ Q_ASSERT(i < path.elementCount());
+
+ Q_ASSERT(data1.type == QPainterPath::CurveToDataElement);
+ Q_ASSERT(data2.type == QPainterPath::CurveToDataElement);
+
+ D2D1_BEZIER_SEGMENT segment;
+
+ segment.point1 = to_d2d_point_2f(element);
+ segment.point2 = to_d2d_point_2f(data1);
+ segment.point3 = to_d2d_point_2f(data2);
+
+ sink->AddBezier(segment);
+ }
+ break;
+
+ case QPainterPath::CurveToDataElement:
+ qWarning("%s: Unhandled Curve Data Element", __FUNCTION__);
+ break;
+ }
+ }
+
+ if (inFigure)
+ sink->EndFigure(D2D1_FIGURE_END_OPEN);
+
+ sink->Close();
+
+ return geometry;
+}
+
+static ComPtr<ID2D1PathGeometry> regionToPathGeometry(const QRegion &region)
+{
+ QPainterPath ppath;
+ ppath.addRegion(region);
+ return painterPathToPathGeometry(ppath);
+}
+
+class QWindowsDirect2DPaintEnginePrivate : public QPaintEnginePrivate
+{
+ Q_DECLARE_PUBLIC(QWindowsDirect2DPaintEngine)
+public:
+ QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm)
+ : bitmap(bm)
+ , clipPushed(false)
+ , hasPerspectiveTransform(false)
+ , opacity(1.0)
+ , renderHints(QPainter::TextAntialiasing)
+ {
+ pen.reset();
+
+ HRESULT hr = factory()->CreateStrokeStyle(D2D1::StrokeStyleProperties(D2D1_CAP_STYLE_ROUND,
+ D2D1_CAP_STYLE_ROUND,
+ D2D1_CAP_STYLE_ROUND),
+ NULL, 0,
+ pointStrokeStyle.ReleaseAndGetAddressOf());
+ if (FAILED(hr))
+ qWarning("%s: Could not create stroke style for points and zero length lines: %#x", __FUNCTION__, hr);
+
+ dc()->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
+ }
+
+ QWindowsDirect2DBitmap *bitmap;
+
+ QPainterPath clipPath;
+ bool clipPushed;
+
+ ComPtr<ID2D1StrokeStyle> pointStrokeStyle;
+ QPointF currentBrushOrigin;
+
+ bool hasPerspectiveTransform;
+
+ qreal opacity;
+
+ struct {
+ qreal width;
+ QColor color;
+ bool isNull;
+ ComPtr<ID2D1Brush> brush;
+ ComPtr<ID2D1StrokeStyle1> strokeStyle;
+
+ inline void reset() {
+ width = defaultPenWidth;
+ color = QColor(Qt::black);
+ isNull = true;
+ brush.Reset();
+ strokeStyle.Reset();
+ }
+ } pen;
+
+ struct {
+ ComPtr<ID2D1Brush> brush;
+ } brush;
+
+ QPainter::RenderHints renderHints;
+
+ inline ID2D1DeviceContext *dc() const
+ {
+ Q_ASSERT(bitmap);
+ return bitmap->deviceContext()->get();
+ }
+
+ inline D2D1_INTERPOLATION_MODE interpolationMode() const
+ {
+ return (renderHints & QPainter::SmoothPixmapTransform) ? D2D1_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC
+ : D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
+ }
+
+ inline D2D1_ANTIALIAS_MODE antialiasMode() const
+ {
+ return (renderHints & QPainter::Antialiasing) ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
+ : D2D1_ANTIALIAS_MODE_ALIASED;
+ }
+
+ void updateState(const QPaintEngineState &state, QPaintEngine::DirtyFlags dirty)
+ {
+ if (dirty & QPaintEngine::DirtyPen)
+ updatePen(state.pen());
+
+ if (dirty & QPaintEngine::DirtyBrush)
+ updateBrush(state.brush());
+
+ if (dirty & QPaintEngine::DirtyBrushOrigin)
+ updateBrushOrigin(state.brushOrigin());
+
+ if (dirty & QPaintEngine::DirtyHints)
+ updateHints(state.renderHints());
+
+ if (dirty & QPaintEngine::DirtyTransform)
+ updateTransform(state.transform());
+
+ if (dirty & QPaintEngine::DirtyClipEnabled)
+ updateClipEnabled(state.isClipEnabled());
+
+ if (dirty & QPaintEngine::DirtyClipPath)
+ updateClipPath(state.clipPath(), state.clipOperation());
+
+ if (dirty & QPaintEngine::DirtyClipRegion)
+ updateClipRegion(state.clipRegion(), state.clipOperation());
+
+ if (dirty & QPaintEngine::DirtyOpacity)
+ updateOpacity(state.opacity());
+ }
+
+ void updateTransform(const QTransform &t)
+ {
+ dc()->SetTransform(to_d2d_matrix_3x2_f(t));
+ hasPerspectiveTransform = !t.isAffine();
+ }
+
+ void updateOpacity(qreal o)
+ {
+ opacity = o;
+ if (brush.brush)
+ brush.brush.Get()->SetOpacity(o);
+ if (pen.brush)
+ pen.brush.Get()->SetOpacity(o);
+ }
+
+ void pushClip()
+ {
+ ComPtr<ID2D1Geometry> geometricMask = painterPathToPathGeometry(clipPath);
+ if (!geometricMask) {
+ qWarning("%s: Could not convert painter path, not pushing clip path!", __FUNCTION__);
+ return;
+ }
+
+ popClip();
+ dc()->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(),
+ geometricMask.Get(),
+ antialiasMode(),
+ D2D1::IdentityMatrix(),
+ 1.0,
+ NULL,
+ D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND),
+ NULL);
+ clipPushed = true;
+ }
+
+ void popClip()
+ {
+ if (clipPushed) {
+ dc()->PopLayer();
+ clipPushed = false;
+ }
+ }
+
+ void updateClipEnabled(bool enabled)
+ {
+ if (!enabled)
+ popClip();
+ else if (!clipPushed)
+ pushClip();
+ }
+
+ void updateClipPath(const QPainterPath &path, Qt::ClipOperation operation)
+ {
+ switch (operation) {
+ case Qt::NoClip:
+ popClip();
+ break;
+ case Qt::ReplaceClip:
+ clipPath = path;
+ pushClip();
+ break;
+ case Qt::IntersectClip:
+ clipPath &= path;
+ pushClip();
+ break;
+ }
+ }
+
+ void updateClipRegion(const QRegion &region, Qt::ClipOperation operation)
+ {
+ QPainterPath p;
+ p.addRegion(region);
+ updateClipPath(p, operation);
+ }
+
+ void updateBrush(const QBrush &newBrush)
+ {
+ brush.brush = to_d2d_brush(newBrush);
+ if (brush.brush) {
+ brush.brush->SetOpacity(opacity);
+ applyBrushOrigin(currentBrushOrigin);
+ }
+ }
+
+ void updateBrushOrigin(const QPointF &origin)
+ {
+ negateCurrentBrushOrigin();
+ applyBrushOrigin(origin);
+ }
+
+ void negateCurrentBrushOrigin()
+ {
+ if (brush.brush && !currentBrushOrigin.isNull()) {
+ D2D1_MATRIX_3X2_F transform;
+ brush.brush->GetTransform(&transform);
+
+ brush.brush->SetTransform(*(D2D1::Matrix3x2F::ReinterpretBaseType(&transform))
+ * D2D1::Matrix3x2F::Translation(-currentBrushOrigin.x(),
+ -currentBrushOrigin.y()));
+ }
+ }
+
+ void applyBrushOrigin(const QPointF &origin)
+ {
+ if (brush.brush && !origin.isNull()) {
+ D2D1_MATRIX_3X2_F transform;
+ brush.brush->GetTransform(&transform);
+
+ brush.brush->SetTransform(*(D2D1::Matrix3x2F::ReinterpretBaseType(&transform))
+ * D2D1::Matrix3x2F::Translation(origin.x(), origin.y()));
+ }
+
+ currentBrushOrigin = origin;
+ }
+
+ void updatePen(const QPen &newPen)
+ {
+ pen.reset();
+
+ if (newPen.style() == Qt::NoPen)
+ return;
+
+ pen.isNull = false;
+ pen.brush = to_d2d_brush(newPen.brush());
+ if (!pen.brush)
+ return;
+
+ pen.width = newPen.widthF();
+ pen.color = newPen.color();
+ pen.brush->SetOpacity(opacity);
+
+ D2D1_STROKE_STYLE_PROPERTIES1 props = {};
+
+ // Try and match Qt's raster engine in output as closely as possible
+ switch (newPen.style()) {
+ case Qt::DotLine:
+ case Qt::DashDotLine:
+ case Qt::DashDotDotLine:
+ if (pen.width <= 1.0) {
+ props.startCap = props.endCap = props.dashCap = D2D1_CAP_STYLE_FLAT;
+ break;
+ }
+ // fall through
+ default:
+ switch (newPen.capStyle()) {
+ case Qt::SquareCap:
+ props.startCap = props.endCap = props.dashCap = D2D1_CAP_STYLE_SQUARE;
+ break;
+ case Qt::RoundCap:
+ props.startCap = props.endCap = props.dashCap = D2D1_CAP_STYLE_ROUND;
+ case Qt::FlatCap:
+ default:
+ props.startCap = props.endCap = props.dashCap = D2D1_CAP_STYLE_FLAT;
+ break;
+ }
+ break;
+ }
+
+ switch (newPen.joinStyle()) {
+ case Qt::BevelJoin:
+ props.lineJoin = D2D1_LINE_JOIN_BEVEL;
+ break;
+ case Qt::RoundJoin:
+ props.lineJoin = D2D1_LINE_JOIN_ROUND;
+ break;
+ case Qt::MiterJoin:
+ default:
+ props.lineJoin = D2D1_LINE_JOIN_MITER;
+ break;
+ }
+
+ props.miterLimit = newPen.miterLimit() * qreal(2.0); // D2D and Qt miter specs differ
+ props.dashOffset = newPen.dashOffset();
+ props.transformType = qIsNull(newPen.widthF()) ? D2D1_STROKE_TRANSFORM_TYPE_HAIRLINE
+ : newPen.isCosmetic() ? D2D1_STROKE_TRANSFORM_TYPE_FIXED
+ : D2D1_STROKE_TRANSFORM_TYPE_NORMAL;
+
+ switch (newPen.style()) {
+ case Qt::SolidLine:
+ props.dashStyle = D2D1_DASH_STYLE_SOLID;
+ break;
+ default:
+ props.dashStyle = D2D1_DASH_STYLE_CUSTOM;
+ break;
+ }
+
+ HRESULT hr;
+
+ if (props.dashStyle == D2D1_DASH_STYLE_CUSTOM) {
+ QVector<qreal> dashes = newPen.dashPattern();
+ QVector<FLOAT> converted(dashes.size());
+
+ for (int i = 0; i < dashes.size(); i++) {
+ converted[i] = dashes[i];
+ }
+
+ hr = factory()->CreateStrokeStyle(props, converted.constData(), converted.size(), &(pen.strokeStyle));
+ } else {
+ hr = factory()->CreateStrokeStyle(props, NULL, 0, &(pen.strokeStyle));
+ }
+
+ if (FAILED(hr))
+ qWarning("%s: Could not create stroke style: %#x", __FUNCTION__, hr);
+ }
+
+ ComPtr<ID2D1Brush> to_d2d_brush(const QBrush &newBrush)
+ {
+ HRESULT hr;
+ ComPtr<ID2D1Brush> result;
+
+ switch (newBrush.style()) {
+ case Qt::NoBrush:
+ break;
+
+ case Qt::SolidPattern:
+ {
+ ComPtr<ID2D1SolidColorBrush> solid;
+
+ hr = dc()->CreateSolidColorBrush(to_d2d_color_f(newBrush.color()), &solid);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create solid color brush: %#x", __FUNCTION__, hr);
+ break;
+ }
+
+ hr = solid.As(&result);
+ if (FAILED(hr))
+ qWarning("%s: Could not convert solid color brush: %#x", __FUNCTION__, hr);
+ }
+ break;
+
+ case Qt::Dense1Pattern:
+ case Qt::Dense2Pattern:
+ case Qt::Dense3Pattern:
+ case Qt::Dense4Pattern:
+ case Qt::Dense5Pattern:
+ case Qt::Dense6Pattern:
+ case Qt::Dense7Pattern:
+ case Qt::HorPattern:
+ case Qt::VerPattern:
+ case Qt::CrossPattern:
+ case Qt::BDiagPattern:
+ case Qt::FDiagPattern:
+ case Qt::DiagCrossPattern:
+ {
+ ComPtr<ID2D1BitmapBrush1> bitmapBrush;
+ D2D1_BITMAP_BRUSH_PROPERTIES1 bitmapBrushProperties = {
+ D2D1_EXTEND_MODE_WRAP,
+ D2D1_EXTEND_MODE_WRAP,
+ interpolationMode()
+ };
+
+ QImage brushImg = qt_imageForBrush(newBrush.style(), false);
+ brushImg.setColor(0, newBrush.color().rgba());
+ brushImg.setColor(1, qRgba(0, 0, 0, 0));
+
+ QWindowsDirect2DBitmap bitmap;
+ bool success = bitmap.fromImage(brushImg, Qt::AutoColor);
+ if (!success) {
+ qWarning("%s: Could not create Direct2D bitmap from Qt pattern brush image", __FUNCTION__);
+ break;
+ }
+
+ hr = dc()->CreateBitmapBrush(bitmap.bitmap(),
+ bitmapBrushProperties,
+ &bitmapBrush);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create Direct2D bitmap brush for Qt pattern brush: %#x", __FUNCTION__, hr);
+ break;
+ }
+
+ hr = bitmapBrush.As(&result);
+ if (FAILED(hr))
+ qWarning("%s: Could not convert Direct2D bitmap brush for Qt pattern brush: %#x", __FUNCTION__, hr);
+ }
+ break;
+
+ case Qt::LinearGradientPattern:
+ case Qt::RadialGradientPattern:
+ case Qt::ConicalGradientPattern:
+ break;
+
+ case Qt::TexturePattern:
+ {
+ ComPtr<ID2D1BitmapBrush1> bitmapBrush;
+ D2D1_BITMAP_BRUSH_PROPERTIES1 bitmapBrushProperties = {
+ D2D1_EXTEND_MODE_WRAP,
+ D2D1_EXTEND_MODE_WRAP,
+ interpolationMode()
+ };
+
+ QWindowsDirect2DPlatformPixmap *pp = static_cast<QWindowsDirect2DPlatformPixmap *>(newBrush.texture().handle());
+ QWindowsDirect2DBitmap *bitmap = pp->bitmap();
+ hr = dc()->CreateBitmapBrush(bitmap->bitmap(),
+ bitmapBrushProperties,
+ &bitmapBrush);
+
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create texture brush: %#x", __FUNCTION__, hr);
+ break;
+ }
+
+ hr = bitmapBrush.As(&result);
+ if (FAILED(hr))
+ qWarning("%s: Could not convert texture brush: %#x", __FUNCTION__, hr);
+ }
+ break;
+ }
+
+ if (result && !newBrush.transform().isIdentity())
+ result->SetTransform(to_d2d_matrix_3x2_f(newBrush.transform()));
+
+ return result;
+ }
+
+ void updateHints(QPainter::RenderHints newHints)
+ {
+ renderHints = newHints;
+ dc()->SetAntialiasMode(antialiasMode());
+ }
+
+ template <typename T>
+ void drawLines(const T* lines, int lineCount)
+ {
+ if (!pen.brush)
+ return;
+
+ for (int i = 0; i < lineCount; i++) {
+ const T &line = lines[i];
+
+ // Try to fit Qt's and Direct2D's idea of zero length line
+ // handling together nicely.
+
+ if (line.p1() == line.p2() && pen.strokeStyle.Get()->GetDashCap() != D2D1_CAP_STYLE_SQUARE) {
+ if (pen.width <= 1.0) {
+ dc()->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
+ // Note that we use pointStrokeStyle here, not the pen's stroke style!
+ dc()->DrawLine(to_d2d_point_2f(line.p1()), to_d2d_point_2f(line.p2()), pen.brush.Get(), pen.width, pointStrokeStyle.Get());
+ dc()->SetAntialiasMode(antialiasMode());
+ }
+ } else
+ dc()->DrawLine(to_d2d_point_2f(line.p1()), to_d2d_point_2f(line.p2()), pen.brush.Get(), pen.width, pen.strokeStyle.Get());
+ }
+ }
+
+ template <typename T>
+ void drawRects(const T* rects, int rectCount)
+ {
+ if (!brush.brush && !pen.brush)
+ return;
+
+ for (int i = 0; i < rectCount; i++) {
+ if (brush.brush)
+ dc()->FillRectangle(to_d2d_rect_f(rects[i]), brush.brush.Get());
+
+ // Direct2D for some reason uses different geometry in FillRectangle and DrawRectangle.
+ // We have to adjust the rect right and down here by one pixel to paint the rectangle properly.
+ if (pen.brush)
+ dc()->DrawRectangle(to_d2d_rect_f(rects[i].adjusted(1, 1, 1, 1)), pen.brush.Get(), pen.width, pen.strokeStyle.Get());
+ }
+ }
+
+ template <typename T>
+ void drawPolygon(const T* points, int pointCount, QPaintEngine::PolygonDrawMode mode)
+ {
+ if (pointCount < 3)
+ return;
+
+ if (!brush.brush && !pen.brush)
+ return;
+
+ QVector<D2D1_POINT_2F> converted(pointCount);
+ for (int i = 0; i < pointCount; i++) {
+ const T &p = points[i];
+ converted[i].x = p.x();
+ converted[i].y = p.y();
+ }
+
+ drawPolygon(converted.constData(), converted.size(), mode);
+ }
+
+ void drawPolygon(const D2D1_POINT_2F *points, int pointCount, QPaintEngine::PolygonDrawMode mode)
+ {
+ ComPtr<ID2D1PathGeometry> geometry;
+ ComPtr<ID2D1GeometrySink> sink;
+ const bool is_polyline = mode == QPaintEngine::PolylineMode;
+
+ HRESULT hr = factory()->CreatePathGeometry(&geometry);
+ if (FAILED(hr))
+ return;
+
+ hr = geometry->Open(&sink);
+ if (FAILED(hr))
+ return;
+
+ switch (mode) {
+ case QPaintEngine::OddEvenMode:
+ sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE);
+ break;
+ case QPaintEngine::WindingMode:
+ sink->SetFillMode(D2D1_FILL_MODE_WINDING);
+ break;
+ case QPaintEngine::ConvexMode:
+ case QPaintEngine::PolylineMode:
+ // XXX
+ break;
+ }
+
+ sink->BeginFigure(points[0], is_polyline ? D2D1_FIGURE_BEGIN_HOLLOW
+ : D2D1_FIGURE_BEGIN_FILLED);
+ sink->AddLines(points + 1, pointCount - 1);
+ sink->EndFigure(is_polyline ? D2D1_FIGURE_END_OPEN
+ : D2D1_FIGURE_END_CLOSED);
+ sink->Close();
+
+ if (brush.brush)
+ dc()->FillGeometry(geometry.Get(), brush.brush.Get());
+
+ if (pen.brush)
+ dc()->DrawGeometry(geometry.Get(), pen.brush.Get(), pen.width, pen.strokeStyle.Get());
+ }
+};
+
+QWindowsDirect2DPaintEngine::QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap)
+ : QPaintEngine(PrimitiveTransform
+ | PatternTransform
+ | PixmapTransform
+ | PatternBrush
+ | AlphaBlend
+ | PainterPaths
+ | Antialiasing
+ | BrushStroke
+ | ConstantOpacity
+ | MaskedBrush
+ | ObjectBoundingModeGradients
+
+ // Although Direct2D 1.1 contains support for both linear and radial gradients,
+ // there unfortunately is no support for repeating or reflecting versions of them
+ //| LinearGradientFill
+ //| RadialGradientFill
+
+ // Unsupported entirely by Direct2D 1.1
+ //| ConicalGradientFill
+
+ // We might be able to support this using Direct2D effects
+ //| PorterDuff
+
+ // Direct2D currently only supports affine transforms directly
+ // We might be able to support this using Direct2D effects
+ //| PerspectiveTransform
+
+ // We might be able to support this using Direct2D effects
+ //| BlendModes
+
+ // We might be able to support this using Direct2D effects
+ //| RasterOpModes
+
+ // We have to inform Direct2D when we start and end drawing
+ //| PaintOutsidePaintEvent
+ )
+ , d_ptr(new QWindowsDirect2DPaintEnginePrivate(bitmap))
+{
+
+}
+
+bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+
+ d->bitmap->deviceContext()->begin();
+ d->dc()->SetTransform(D2D1::Matrix3x2F::Identity());
+
+ QRect clip(0, 0, pdev->width(), pdev->height());
+ if (!systemClip().isEmpty()) {
+ clip &= systemClip().boundingRect();
+ }
+ d->dc()->PushAxisAlignedClip(to_d2d_rect_f(clip), d->antialiasMode());
+ updateState(*state);
+
+ D2D_TAG(D2DDebugDrawInitialStateTag);
+
+ return true;
+}
+
+bool QWindowsDirect2DPaintEngine::end()
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ d->popClip();
+ d->dc()->PopAxisAlignedClip();
+ return d->bitmap->deviceContext()->end();
+}
+
+void QWindowsDirect2DPaintEngine::updateState(const QPaintEngineState &state)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ d->updateState(state, state.state());
+}
+
+QPaintEngine::Type QWindowsDirect2DPaintEngine::type() const
+{
+ return QPaintEngine::Direct2D;
+}
+
+void QWindowsDirect2DPaintEngine::drawEllipse(const QRectF &rect)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawEllipseTag);
+
+ D2D1_ELLIPSE ellipse = {
+ to_d2d_point_2f(rect.center()),
+ rect.width() / 2,
+ rect.height() / 2
+ };
+
+ 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.width, d->pen.strokeStyle.Get());
+ }
+}
+
+void QWindowsDirect2DPaintEngine::drawEllipse(const QRect &rect)
+{
+ drawEllipse(QRectF(rect));
+}
+
+void QWindowsDirect2DPaintEngine::drawImage(const QRectF &rectangle, const QImage &image,
+ const QRectF &sr, Qt::ImageConversionFlags flags)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawImageTag);
+
+ QPixmap pixmap = QPixmap::fromImage(image, flags);
+ drawPixmap(rectangle, pixmap, sr);
+}
+
+void QWindowsDirect2DPaintEngine::drawLines(const QLineF *lines, int lineCount)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawLinesTag);
+ d->drawLines(lines, lineCount);
+}
+
+void QWindowsDirect2DPaintEngine::drawLines(const QLine *lines, int lineCount)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawLinesTag);
+ d->drawLines(lines, lineCount);
+}
+
+void QWindowsDirect2DPaintEngine::drawPath(const QPainterPath &path)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawPathTag);
+
+ if (path.elementCount() == 0)
+ return;
+
+ if (!d->brush.brush && !d->pen.brush)
+ return;
+
+ ComPtr<ID2D1PathGeometry> geometry = painterPathToPathGeometry(path);
+ if (!geometry)
+ return;
+
+ if (d->brush.brush)
+ d->dc()->FillGeometry(geometry.Get(), d->brush.brush.Get());
+
+ if (d->pen.brush)
+ d->dc()->DrawGeometry(geometry.Get(), d->pen.brush.Get(), d->pen.width, d->pen.strokeStyle.Get());
+}
+
+void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
+ const QPixmap &pm,
+ const QRectF &sr)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawPixmapTag);
+
+ if (pm.isNull())
+ return;
+
+ if (pm.handle()->pixelType() == QPlatformPixmap::BitmapType) {
+ QImage i = pm.toImage();
+ i.setColor(0, qRgba(0, 0, 0, 0));
+ i.setColor(1, d->pen.color.rgba());
+ drawImage(r, i, sr);
+ return;
+ }
+
+ QWindowsDirect2DPlatformPixmap *pp = static_cast<QWindowsDirect2DPlatformPixmap *>(pm.handle());
+ QWindowsDirect2DBitmap *bitmap = pp->bitmap();
+
+ if (bitmap->bitmap() != d->bitmap->bitmap()) {
+ // Good, src bitmap != dst bitmap
+ if (sr.isValid())
+ d->dc()->DrawBitmap(bitmap->bitmap(),
+ to_d2d_rect_f(r), d->opacity,
+ d->interpolationMode(),
+ to_d2d_rect_f(sr));
+ else
+ d->dc()->DrawBitmap(bitmap->bitmap(),
+ to_d2d_rect_f(r), d->opacity,
+ d->interpolationMode());
+ } else {
+ // Ok, so the source pixmap and destination pixmap is the same.
+ // D2D is not fond of this scenario, deal with it through
+ // an intermediate bitmap
+ QWindowsDirect2DBitmap intermediate;
+
+ if (sr.isValid()) {
+ bool r = intermediate.resize(sr.width(), sr.height());
+ if (!r) {
+ qDebug("%s: Could not resize intermediate bitmap to source rect size", __FUNCTION__);
+ return;
+ }
+
+ D2D1_RECT_U d2d_sr = to_d2d_rect_u(sr.toRect());
+ HRESULT hr = intermediate.bitmap()->CopyFromBitmap(NULL,
+ bitmap->bitmap(),
+ &d2d_sr);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not copy source rect area from source bitmap to intermediate bitmap: %#x", __FUNCTION__, hr);
+ return;
+ }
+ } else {
+ bool r = intermediate.resize(bitmap->size().width(),
+ bitmap->size().height());
+ if (!r) {
+ qDebug("%s: Could not resize intermediate bitmap to source bitmap size", __FUNCTION__);
+ return;
+ }
+
+ HRESULT hr = intermediate.bitmap()->CopyFromBitmap(NULL,
+ bitmap->bitmap(),
+ NULL);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not copy source bitmap to intermediate bitmap: %#x", __FUNCTION__, hr);
+ return;
+ }
+ }
+
+ d->dc()->DrawBitmap(intermediate.bitmap(),
+ to_d2d_rect_f(r), d->opacity,
+ d->interpolationMode());
+ }
+}
+
+void QWindowsDirect2DPaintEngine::drawPolygon(const QPointF *points,
+ int pointCount,
+ QPaintEngine::PolygonDrawMode mode)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawPolygonTag);
+ d->drawPolygon(points, pointCount, mode);
+}
+
+void QWindowsDirect2DPaintEngine::drawPolygon(const QPoint *points,
+ int pointCount,
+ QPaintEngine::PolygonDrawMode mode)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawPolygonTag);
+ d->drawPolygon(points, pointCount, mode);
+}
+
+void QWindowsDirect2DPaintEngine::drawRects(const QRectF *rects, int rectCount)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawRectsTag);
+ d->drawRects(rects, rectCount);
+}
+
+void QWindowsDirect2DPaintEngine::drawRects(const QRect *rects, int rectCount)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawRectsTag);
+ d->drawRects(rects, rectCount);
+}
+
+// Points (1/72 inches) to Microsoft's Device Independent Pixels (1/96 inches)
+inline static Q_DECL_CONSTEXPR FLOAT pointSizeToDIP(qreal pointSize)
+{
+ return pointSize + (pointSize / qreal(3.0));
+}
+
+inline static FLOAT pixelSizeToDIP(int pixelSize)
+{
+ FLOAT dpiX, dpiY;
+ factory()->GetDesktopDpi(&dpiX, &dpiY);
+
+ return FLOAT(pixelSize) / (dpiY / 96.0f);
+}
+
+inline static FLOAT fontSizeInDIP(const QFont &font)
+{
+ // Microsoft wants the font size in DIPs (Device Independent Pixels), each of which is 1/96 inches.
+ if (font.pixelSize() == -1) {
+ // font size was set as points
+ return pointSizeToDIP(font.pointSizeF());
+ } else {
+ // font size was set as pixels
+ return pixelSizeToDIP(font.pixelSize());
+ }
+}
+
+void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawTextItemTag);
+
+ if (d->pen.isNull)
+ return;
+
+ // If we can't support the current configuration with Direct2D, fall back to slow path
+ // Most common cases are perspective transform and gradient brush as pen
+ if (d->hasPerspectiveTransform || !d->pen.brush) {
+ QPaintEngine::drawTextItem(p, textItem);
+ return;
+ }
+
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+ ComPtr<IDWriteFontFace> fontFace;
+
+ switch (ti.fontEngine->type()) {
+ case QFontEngine::Win:
+ {
+ QWindowsFontEngine *wfe = static_cast<QWindowsFontEngine *>(ti.fontEngine);
+ 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);
+
+ }
+ break;
+
+#ifndef QT_NO_DIRECTWRITE
+
+ case QFontEngine::DirectWrite:
+ {
+ QWindowsFontEngineDirectWrite *wfedw = static_cast<QWindowsFontEngineDirectWrite *>(ti.fontEngine);
+ fontFace = wfedw->directWriteFontFace();
+ }
+ break;
+
+#endif // QT_NO_DIRECTWRITE
+
+ default:
+ qDebug("%s: Unknown font engine!", __FUNCTION__);
+ break;
+ }
+
+ if (!fontFace) {
+ qDebug("%s: Could not find font - falling back to slow text rendering path.", __FUNCTION__);
+ QPaintEngine::drawTextItem(p, textItem);
+ return;
+ }
+
+ QVector<UINT16> glyphIndices(ti.glyphs.numGlyphs);
+ QVector<FLOAT> glyphAdvances(ti.glyphs.numGlyphs);
+ QVector<DWRITE_GLYPH_OFFSET> glyphOffsets(ti.glyphs.numGlyphs);
+
+ // Imperfect conversion here
+ for (int i = 0; i < ti.glyphs.numGlyphs; i++) {
+ glyphIndices[i] = UINT16(ti.glyphs.glyphs[i]);
+ glyphAdvances[i] = ti.glyphs.effectiveAdvance(i).toReal();
+ glyphOffsets[i].advanceOffset = ti.glyphs.offsets[i].x.toReal();
+ glyphOffsets[i].ascenderOffset = ti.glyphs.offsets[i].y.toReal();
+ }
+
+ const bool rtl = (ti.flags & QTextItem::RightToLeft);
+ const UINT32 bidiLevel = rtl ? 1 : 0;
+
+ DWRITE_GLYPH_RUN glyphRun = {
+ fontFace.Get(), // IDWriteFontFace *fontFace;
+ fontSizeInDIP(ti.font()), // FLOAT fontEmSize;
+ ti.glyphs.numGlyphs, // UINT32 glyphCount;
+ glyphIndices.constData(), // const UINT16 *glyphIndices;
+ glyphAdvances.constData(), // const FLOAT *glyphAdvances;
+ glyphOffsets.constData(), // const DWRITE_GLYPH_OFFSET *glyphOffsets;
+ FALSE, // BOOL isSideways;
+ bidiLevel // UINT32 bidiLevel;
+ };
+
+ const bool antiAlias = bool((d->renderHints & QPainter::TextAntialiasing)
+ && !(ti.font().styleStrategy() & QFont::NoAntialias));
+ d->dc()->SetTextAntialiasMode(antiAlias ? D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE
+ : D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
+
+ const QPointF offset(rtl ? ti.width.toReal() : 0, 0);
+ d->dc()->DrawGlyphRun(to_d2d_point_2f(p + offset),
+ &glyphRun,
+ NULL,
+ d->pen.brush.Get(),
+ DWRITE_MEASURING_MODE_GDI_CLASSIC);
+}
+
+static void qt_draw_tile(QPaintEngine *gc, qreal x, qreal y, qreal w, qreal h,
+ const QPixmap &pixmap, qreal xOffset, qreal yOffset)
+{
+ qreal yPos, xPos, drawH, drawW, yOff, xOff;
+ yPos = y;
+ yOff = yOffset;
+ while (yPos < y + h) {
+ drawH = pixmap.height() - yOff; // Cropping first row
+ if (yPos + drawH > y + h) // Cropping last row
+ drawH = y + h - yPos;
+ xPos = x;
+ xOff = xOffset;
+ while (xPos < x + w) {
+ drawW = pixmap.width() - xOff; // Cropping first column
+ if (xPos + drawW > x + w) // Cropping last column
+ drawW = x + w - xPos;
+ if (drawW > 0 && drawH > 0)
+ gc->drawPixmap(QRectF(xPos, yPos, drawW, drawH), pixmap, QRectF(xOff, yOff, drawW, drawH));
+ xPos += drawW;
+ xOff = 0;
+ }
+ yPos += drawH;
+ yOff = 0;
+ }
+}
+
+void QWindowsDirect2DPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+ D2D_TAG(D2DDebugDrawTextItemTag);
+ qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), pixmap, p.x(), p.y());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
new file mode 100644
index 0000000000..554380cb1f
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DPAINTENGINE_H
+#define QWINDOWSDIRECT2DPAINTENGINE_H
+
+#include <QtCore/QScopedPointer>
+#include <QtGui/QPaintEngine>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DPaintEnginePrivate;
+class QWindowsDirect2DBitmap;
+
+class QWindowsDirect2DPaintEngine : public QPaintEngine
+{
+ Q_DECLARE_PRIVATE(QWindowsDirect2DPaintEngine)
+
+public:
+ QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap);
+
+ bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE;
+ bool end() Q_DECL_OVERRIDE;
+
+ void updateState(const QPaintEngineState &state) Q_DECL_OVERRIDE;
+
+ Type type() const Q_DECL_OVERRIDE;
+
+ void drawEllipse(const QRectF &rect) Q_DECL_OVERRIDE;
+ void drawEllipse(const QRect &rect) Q_DECL_OVERRIDE;
+ void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE;
+ void drawLines(const QLineF *lines, int lineCount) Q_DECL_OVERRIDE;
+ void drawLines(const QLine *lines, int lineCount) Q_DECL_OVERRIDE;
+ void drawPath(const QPainterPath &path) Q_DECL_OVERRIDE;
+ void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) Q_DECL_OVERRIDE;
+ void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE;
+ void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE;
+ void drawRects(const QRectF *rects, int rectCount) Q_DECL_OVERRIDE;
+ void drawRects(const QRect *rects, int rectCount) Q_DECL_OVERRIDE;
+ void drawTextItem(const QPointF &p, const QTextItem &textItem) Q_DECL_OVERRIDE;
+ void drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p) Q_DECL_OVERRIDE;
+
+private:
+ QScopedPointer<QWindowsDirect2DPaintEnginePrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DPAINTENGINE_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
new file mode 100644
index 0000000000..072c4b3c0e
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dcontext.h"
+#include "qwindowsdirect2dpaintdevice.h"
+#include "qwindowsdirect2dplatformpixmap.h"
+#include "qwindowsdirect2dbitmap.h"
+#include "qwindowsdirect2dhelpers.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QImage>
+#include <QtGui/QPaintDevice>
+#include <QtGui/QPaintEngine>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DPlatformPixmapPrivate
+{
+public:
+ QWindowsDirect2DPlatformPixmapPrivate()
+ : bitmap(new QWindowsDirect2DBitmap)
+ , device(new QWindowsDirect2DPaintDevice(bitmap.data(), QInternal::Pixmap))
+ , devicePixelRatio(1.0)
+ {}
+
+ QScopedPointer<QWindowsDirect2DBitmap> bitmap;
+ QScopedPointer<QWindowsDirect2DPaintDevice> device;
+ qreal devicePixelRatio;
+};
+
+static int qt_d2dpixmap_serno = 0;
+
+QWindowsDirect2DPlatformPixmap::QWindowsDirect2DPlatformPixmap(PixelType pixelType)
+ : QPlatformPixmap(pixelType, Direct2DClass)
+ , d_ptr(new QWindowsDirect2DPlatformPixmapPrivate)
+{
+ setSerialNumber(qt_d2dpixmap_serno++);
+}
+
+QWindowsDirect2DPlatformPixmap::~QWindowsDirect2DPlatformPixmap()
+{
+
+}
+
+void QWindowsDirect2DPlatformPixmap::resize(int width, int height)
+{
+ Q_D(QWindowsDirect2DPlatformPixmap);
+
+ if (!d->bitmap->resize(width, height)) {
+ qWarning("%s: Could not resize bitmap", __FUNCTION__);
+ return;
+ }
+
+ is_null = false;
+ w = width;
+ h = height;
+ this->d = 32;
+}
+
+void QWindowsDirect2DPlatformPixmap::fromImage(const QImage &image,
+ Qt::ImageConversionFlags flags)
+{
+ Q_D(QWindowsDirect2DPlatformPixmap);
+
+ if (!d->bitmap->fromImage(image, flags)) {
+ qWarning("%s: Could not init from image", __FUNCTION__);
+ return;
+ }
+
+ is_null = false;
+ w = image.width();
+ h = image.height();
+ this->d = 32;
+}
+
+int QWindowsDirect2DPlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ Q_D(const QWindowsDirect2DPlatformPixmap);
+
+ Q_GUI_EXPORT int qt_paint_device_metric(const QPaintDevice *device, QPaintDevice::PaintDeviceMetric metric);
+ return qt_paint_device_metric(d->device.data(), metric);
+}
+
+void QWindowsDirect2DPlatformPixmap::fill(const QColor &color)
+{
+ Q_D(QWindowsDirect2DPlatformPixmap);
+ d->bitmap->fill(color);
+}
+
+bool QWindowsDirect2DPlatformPixmap::hasAlphaChannel() const
+{
+ return true;
+}
+
+QImage QWindowsDirect2DPlatformPixmap::toImage() const
+{
+ return toImage(QRect());
+}
+
+QImage QWindowsDirect2DPlatformPixmap::toImage(const QRect &rect) const
+{
+ Q_D(const QWindowsDirect2DPlatformPixmap);
+
+ bool active = d->device->paintEngine()->isActive();
+
+ if (active)
+ d->device->paintEngine()->end();
+
+ QImage result = d->bitmap->toImage(rect);
+
+ if (active)
+ d->device->paintEngine()->begin(d->device.data());
+
+ return result;
+}
+
+QPaintEngine* QWindowsDirect2DPlatformPixmap::paintEngine() const
+{
+ Q_D(const QWindowsDirect2DPlatformPixmap);
+ return d->device->paintEngine();
+}
+
+qreal QWindowsDirect2DPlatformPixmap::devicePixelRatio() const
+{
+ Q_D(const QWindowsDirect2DPlatformPixmap);
+ return d->devicePixelRatio;
+}
+
+void QWindowsDirect2DPlatformPixmap::setDevicePixelRatio(qreal scaleFactor)
+{
+ Q_D(QWindowsDirect2DPlatformPixmap);
+ d->devicePixelRatio = scaleFactor;
+}
+
+QWindowsDirect2DBitmap *QWindowsDirect2DPlatformPixmap::bitmap() const
+{
+ Q_D(const QWindowsDirect2DPlatformPixmap);
+ return d->bitmap.data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
new file mode 100644
index 0000000000..e6684ea423
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSDIRECT2DPLATFORMPIXMAP_H
+#define QWINDOWSDIRECT2DPLATFORMPIXMAP_H
+
+#include <QtGui/qpa/qplatformpixmap.h>
+#include <QtCore/QScopedPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DPlatformPixmapPrivate;
+class QWindowsDirect2DBitmap;
+
+class QWindowsDirect2DPlatformPixmap : public QPlatformPixmap
+{
+ Q_DECLARE_PRIVATE(QWindowsDirect2DPlatformPixmap)
+public:
+ QWindowsDirect2DPlatformPixmap(PixelType pixelType);
+ ~QWindowsDirect2DPlatformPixmap();
+
+ virtual void resize(int width, int height);
+ virtual void fromImage(const QImage &image,
+ Qt::ImageConversionFlags flags);
+
+ virtual int metric(QPaintDevice::PaintDeviceMetric metric) const;
+ virtual void fill(const QColor &color);
+
+ virtual bool hasAlphaChannel() const;
+
+ virtual QImage toImage() const;
+ virtual QImage toImage(const QRect &rect) const;
+
+ virtual QPaintEngine* paintEngine() const;
+
+ virtual qreal devicePixelRatio() const;
+ virtual void setDevicePixelRatio(qreal scaleFactor);
+
+ QWindowsDirect2DBitmap *bitmap() const;
+
+private:
+ QScopedPointer<QWindowsDirect2DPlatformPixmapPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSDIRECT2DPLATFORMPIXMAP_H
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp
new file mode 100644
index 0000000000..f75bb49fd9
--- /dev/null
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** 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$
+**
+****************************************************************************/
+
+#include "qwindowsdirect2dintegration.h"
+
+#include <QtGui/qpa/qplatformintegrationplugin.h>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsDirect2DIntegrationPlugin : public QPlatformIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "direct2d.json")
+public:
+ QPlatformIntegration *create(const QString&, const QStringList&);
+};
+
+QPlatformIntegration *QWindowsDirect2DIntegrationPlugin::create(const QString& system, const QStringList& paramList)
+{
+ if (system.compare(system, QStringLiteral("direct2d"), Qt::CaseInsensitive) == 0)
+ return QWindowsDirect2DIntegration::create(paramList);
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "qwindowsdirect2dplatformplugin.moc"
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index 4a7c3b279f..584efa1665 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -18,6 +18,10 @@ mac {
win32:!winrt: SUBDIRS += windows
winrt: SUBDIRS += winrt
+contains(QT_CONFIG, direct2d) {
+ SUBDIRS += direct2d
+}
+
qnx {
SUBDIRS += qnx
}
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index 3ad9339f4f..c0f37feb25 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -182,6 +182,7 @@ Configure::Configure(int& argc, char** argv)
dictionary[ "QML_DEBUG" ] = "yes";
dictionary[ "PLUGIN_MANIFESTS" ] = "no";
dictionary[ "DIRECTWRITE" ] = "no";
+ dictionary[ "DIRECT2D" ] = "no";
dictionary[ "NIS" ] = "no";
dictionary[ "NEON" ] = "auto";
dictionary[ "LARGE_FILE" ] = "yes";
@@ -1218,6 +1219,12 @@ void Configure::parseCmdLine()
dictionary["DIRECTWRITE"] = "no";
}
+ else if (configCmdLine.at(i) == "-direct2d") {
+ dictionary["DIRECT2D"] = "yes";
+ } else if (configCmdLine.at(i) == "-no-direct2d") {
+ dictionary["DIRECT2D"] = "no";
+ }
+
else if (configCmdLine.at(i) == "-nis") {
dictionary["NIS"] = "yes";
} else if (configCmdLine.at(i) == "-no-nis") {
@@ -1939,6 +1946,11 @@ bool Configure::displayHelp()
desc("DIRECTWRITE", "no", "-no-directwrite", "Do not build support for DirectWrite font rendering.");
desc("DIRECTWRITE", "yes", "-directwrite", "Build support for DirectWrite font rendering (experimental, requires DirectWrite availability on target systems, e.g. Windows Vista with Platform Update, Windows 7, etc.)\n");
+ desc("DIRECT2D", "no", "-no-direct2d", "Do not build the Direct2D platform plugin.");
+ desc("DIRECT2D", "yes", "-direct2d", "Build the Direct2D platform plugin (experimental,\n"
+ "requires Direct2D availability on target systems,\n"
+ "e.g. Windows 7 with Platform Update, Windows 8, etc.)\n");
+
desc( "-no-style-<style>", "Disable <style> entirely.");
desc( "-qt-style-<style>", "Enable <style> in the Qt Library.\nAvailable styles: ");
@@ -2206,6 +2218,8 @@ bool Configure::checkAvailability(const QString &part)
available = findFile("mfapi.h") && findFile("mf.lib");
} else if (part == "DIRECTWRITE") {
available = findFile("dwrite.h") && findFile("d2d1.h") && findFile("dwrite.lib");
+ } else if (part == "DIRECT2D") {
+ available = tryCompileProject("qpa/direct2d");
} else if (part == "ICONV") {
available = tryCompileProject("unix/iconv") || tryCompileProject("unix/gnu-libiconv");
} else if (part == "INOTIFY") {
@@ -2441,6 +2455,13 @@ bool Configure::verifyConfiguration()
prompt = true;
}
+ if (dictionary["DIRECT2D"] == "yes" && !checkAvailability("DIRECT2D")) {
+ cout << "WARNING: To be able to build the Direct2D platform plugin you will" << endl
+ << "need the Microsoft DirectWrite and Microsoft Direct2D development" << endl
+ << "files such as headers and libraries." << endl;
+ prompt = true;
+ }
+
// -angle given on command line, but Direct X cannot be found.
if (dictionary["ANGLE"] != "no") {
QString errorMessage;
@@ -2730,6 +2751,9 @@ void Configure::generateOutputVars()
if (dictionary["DIRECTWRITE"] == "yes")
qtConfig += "directwrite";
+ if (dictionary["DIRECT2D"] == "yes")
+ qtConfig += "direct2d";
+
if (dictionary[ "NATIVE_GESTURES" ] == "yes")
qtConfig += "native-gestures";
@@ -3574,6 +3598,11 @@ void Configure::displayConfig()
sout << "Use system proxies.........." << dictionary[ "SYSTEM_PROXIES" ] << endl;
sout << endl;
+ sout << "QPA Backends:" << endl;
+ sout << " GDI....................." << "yes" << endl;
+ sout << " Direct2D................" << dictionary[ "DIRECT2D" ] << endl;
+ sout << endl;
+
sout << "Third Party Libraries:" << endl;
sout << " ZLIB support............" << dictionary[ "ZLIB" ] << endl;
sout << " GIF support............." << dictionary[ "GIF" ] << endl;