From b9362903b339e57362a7a3296904504521d0e26f Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Wed, 4 Dec 2013 13:40:23 +0200 Subject: 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 --- src/plugins/platforms/direct2d/direct2d.json | 3 + src/plugins/platforms/direct2d/direct2d.pro | 39 + .../direct2d/qwindowsdirect2dbackingstore.cpp | 239 +++++ .../direct2d/qwindowsdirect2dbackingstore.h | 76 ++ .../platforms/direct2d/qwindowsdirect2dbitmap.cpp | 205 ++++ .../platforms/direct2d/qwindowsdirect2dbitmap.h | 81 ++ .../platforms/direct2d/qwindowsdirect2dcontext.cpp | 218 ++++ .../platforms/direct2d/qwindowsdirect2dcontext.h | 84 ++ .../direct2d/qwindowsdirect2ddevicecontext.cpp | 135 +++ .../direct2d/qwindowsdirect2ddevicecontext.h | 95 ++ .../platforms/direct2d/qwindowsdirect2dhelpers.h | 96 ++ .../direct2d/qwindowsdirect2dintegration.cpp | 122 +++ .../direct2d/qwindowsdirect2dintegration.h | 78 ++ .../direct2d/qwindowsdirect2dnativeinterface.cpp | 64 ++ .../direct2d/qwindowsdirect2dnativeinterface.h | 58 + .../direct2d/qwindowsdirect2dpaintdevice.cpp | 131 +++ .../direct2d/qwindowsdirect2dpaintdevice.h | 71 ++ .../direct2d/qwindowsdirect2dpaintengine.cpp | 1116 ++++++++++++++++++++ .../direct2d/qwindowsdirect2dpaintengine.h | 87 ++ .../direct2d/qwindowsdirect2dplatformpixmap.cpp | 179 ++++ .../direct2d/qwindowsdirect2dplatformpixmap.h | 85 ++ .../direct2d/qwindowsdirect2dplatformplugin.cpp | 66 ++ src/plugins/platforms/platforms.pro | 4 + 23 files changed, 3332 insertions(+) create mode 100644 src/plugins/platforms/direct2d/direct2d.json create mode 100644 src/plugins/platforms/direct2d/direct2d.pro create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h create mode 100644 src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp (limited to 'src/plugins') 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 +#include + +#include +#include +#include + +using Microsoft::WRL::ComPtr; + +QT_BEGIN_NAMESPACE + +class QWindowsDirect2DBackingStorePrivate +{ +public: + QWindowsDirect2DBackingStorePrivate() {} + + ComPtr swapChain; + QSharedPointer backingStore; + QScopedPointer 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 deviceContext; + ComPtr backBufferSurface; + ComPtr 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 ®ion) +{ + 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(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 +#include + +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 ®ion, 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 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 +#include + +#include + +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 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(mappedRect.bits), + size.width, size.height, mappedRect.pitch, + QImage::Format_ARGB32_Premultiplied).copy(rect); + } + + QScopedPointer deviceContext; + ComPtr 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 +#include + +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 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 +#include +#include +#include +#include +#include + +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 dxgiDevice; + ComPtr 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(&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 d3dDevice; + ComPtr d2dFactory; + ComPtr d2dDevice; + ComPtr dxgiFactory; + ComPtr d3dDeviceContext; + ComPtr directWriteFactory; + ComPtr 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 + +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 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 + +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 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 + +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 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 +#include +#include +#include +#include + +#include + +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 +#include + +QT_BEGIN_NAMESPACE + +class QWindowsDirect2DIntegrationPrivate +{ +public: + QWindowsDirect2DNativeInterface m_nativeInterface; + QWindowsDirect2DContext m_d2dContext; +}; + +QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::create(const QStringList ¶mList) +{ + QWindowsDirect2DIntegration *integration = new QWindowsDirect2DIntegration(paramList); + + if (!integration->init()) { + delete integration; + integration = 0; + } + + return integration; +} + +QWindowsDirect2DIntegration::~QWindowsDirect2DIntegration() +{ + +} + + QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::instance() + { + return static_cast(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 ¶mList) + : 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 + +QT_BEGIN_NAMESPACE + +class QWindowsDirect2DContext; +class QWindowsDirect2DIntegrationPrivate; + +class QWindowsDirect2DIntegration : public QWindowsIntegration +{ +public: + static QWindowsDirect2DIntegration *create(const QStringList ¶mList); + + 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 ¶mList); + bool init(); + + QScopedPointer 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 + +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 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 +#include + +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 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 +#include +#include +#include + +#include +#include + +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 painterPathToPathGeometry(const QPainterPath &path) +{ + ComPtr geometry; + ComPtr 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 regionToPathGeometry(const QRegion ®ion) +{ + 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 pointStrokeStyle; + QPointF currentBrushOrigin; + + bool hasPerspectiveTransform; + + qreal opacity; + + struct { + qreal width; + QColor color; + bool isNull; + ComPtr brush; + ComPtr strokeStyle; + + inline void reset() { + width = defaultPenWidth; + color = QColor(Qt::black); + isNull = true; + brush.Reset(); + strokeStyle.Reset(); + } + } pen; + + struct { + ComPtr 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 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 ®ion, 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 dashes = newPen.dashPattern(); + QVector 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 to_d2d_brush(const QBrush &newBrush) + { + HRESULT hr; + ComPtr result; + + switch (newBrush.style()) { + case Qt::NoBrush: + break; + + case Qt::SolidPattern: + { + ComPtr 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 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 bitmapBrush; + D2D1_BITMAP_BRUSH_PROPERTIES1 bitmapBrushProperties = { + D2D1_EXTEND_MODE_WRAP, + D2D1_EXTEND_MODE_WRAP, + interpolationMode() + }; + + QWindowsDirect2DPlatformPixmap *pp = static_cast(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 + 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 + 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 + void drawPolygon(const T* points, int pointCount, QPaintEngine::PolygonDrawMode mode) + { + if (pointCount < 3) + return; + + if (!brush.brush && !pen.brush) + return; + + QVector 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 geometry; + ComPtr 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 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(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(textItem); + ComPtr fontFace; + + switch (ti.fontEngine->type()) { + case QFontEngine::Win: + { + QWindowsFontEngine *wfe = static_cast(ti.fontEngine); + QSharedPointer 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(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 glyphIndices(ti.glyphs.numGlyphs); + QVector glyphAdvances(ti.glyphs.numGlyphs); + QVector 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 +#include + +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 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 +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QWindowsDirect2DPlatformPixmapPrivate +{ +public: + QWindowsDirect2DPlatformPixmapPrivate() + : bitmap(new QWindowsDirect2DBitmap) + , device(new QWindowsDirect2DPaintDevice(bitmap.data(), QInternal::Pixmap)) + , devicePixelRatio(1.0) + {} + + QScopedPointer bitmap; + QScopedPointer 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 +#include + +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 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 +#include + +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 } -- cgit v1.2.3