1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qwindowsdirect2dbitmap.h"
41 #include "qwindowsdirect2dcontext.h"
42 #include "qwindowsdirect2dhelpers.h"
43 #include "qwindowsdirect2ddevicecontext.h"
44
45 #include <QtGui/qimage.h>
46 #include <QtGui/qcolor.h>
47
48 #include <wrl.h>
49
50 using Microsoft::WRL::ComPtr;
51
52 QT_BEGIN_NAMESPACE
53
54 class QWindowsDirect2DBitmapPrivate
55 {
56 public:
QWindowsDirect2DBitmapPrivate(ID2D1DeviceContext * dc=nullptr,ID2D1Bitmap1 * bm=nullptr)57 QWindowsDirect2DBitmapPrivate(ID2D1DeviceContext *dc = nullptr,
58 ID2D1Bitmap1 *bm = nullptr)
59 : deviceContext(new QWindowsDirect2DDeviceContext(dc))
60 , bitmap(bm)
61
62 {
63 deviceContext->get()->SetTarget(bm);
64 }
65
bitmapProperties() const66 D2D1_BITMAP_PROPERTIES1 bitmapProperties() const
67 {
68 FLOAT dpiX, dpiY;
69 QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&dpiX, &dpiY);
70
71 return D2D1::BitmapProperties1(
72 D2D1_BITMAP_OPTIONS_TARGET,
73 D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
74 D2D1_ALPHA_MODE_PREMULTIPLIED),
75 dpiX, dpiY);
76
77 }
78
resize(int width,int height,const void * data=nullptr,int pitch=0)79 bool resize(int width, int height, const void *data = nullptr, int pitch = 0)
80 {
81 deviceContext->get()->SetTarget(nullptr);
82 bitmap.Reset();
83
84 D2D1_SIZE_U size = {
85 UINT32(width), UINT32(height)
86 };
87
88 HRESULT hr = deviceContext->get()->CreateBitmap(size, data, UINT32(pitch),
89 bitmapProperties(),
90 bitmap.ReleaseAndGetAddressOf());
91 if (SUCCEEDED(hr))
92 deviceContext->get()->SetTarget(bitmap.Get());
93 else
94 qWarning("%s: Could not create bitmap: %#lx", __FUNCTION__, hr);
95
96 return SUCCEEDED(hr);
97 }
98
toImage(const QRect & rect)99 QImage toImage(const QRect &rect)
100 {
101 if (!bitmap)
102 return QImage();
103
104 ComPtr<ID2D1Bitmap1> mappingCopy;
105
106 HRESULT hr = S_OK;
107 D2D1_SIZE_U size = bitmap->GetPixelSize();
108
109 D2D1_BITMAP_PROPERTIES1 properties = bitmapProperties();
110 properties.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ;
111
112 hr = deviceContext->get()->CreateBitmap(size, nullptr, 0,
113 properties, &mappingCopy);
114 if (FAILED(hr)) {
115 qWarning("%s: Could not create bitmap: %#lx", __FUNCTION__, hr);
116 return QImage();
117 }
118
119 hr = mappingCopy->CopyFromBitmap(nullptr, bitmap.Get(), nullptr);
120 if (FAILED(hr)) {
121 qWarning("%s: Could not copy from bitmap: %#lx", __FUNCTION__, hr);
122 return QImage();
123 }
124
125 D2D1_MAPPED_RECT mappedRect;
126 hr = mappingCopy->Map(D2D1_MAP_OPTIONS_READ, &mappedRect);
127 if (FAILED(hr)) {
128 qWarning("%s: Could not map: %#lx", __FUNCTION__, hr);
129 return QImage();
130 }
131
132 return QImage(static_cast<const uchar *>(mappedRect.bits),
133 int(size.width), int(size.height), int(mappedRect.pitch),
134 QImage::Format_ARGB32_Premultiplied).copy(rect);
135 }
136
137 QScopedPointer<QWindowsDirect2DDeviceContext> deviceContext;
138 ComPtr<ID2D1Bitmap1> bitmap;
139 };
140
QWindowsDirect2DBitmap()141 QWindowsDirect2DBitmap::QWindowsDirect2DBitmap()
142 : d_ptr(new QWindowsDirect2DBitmapPrivate)
143 {
144 }
145
QWindowsDirect2DBitmap(ID2D1Bitmap1 * bitmap,ID2D1DeviceContext * dc)146 QWindowsDirect2DBitmap::QWindowsDirect2DBitmap(ID2D1Bitmap1 *bitmap, ID2D1DeviceContext *dc)
147 : d_ptr(new QWindowsDirect2DBitmapPrivate(dc, bitmap))
148 {
149 }
150
~QWindowsDirect2DBitmap()151 QWindowsDirect2DBitmap::~QWindowsDirect2DBitmap()
152 {
153 }
154
resize(int width,int height)155 bool QWindowsDirect2DBitmap::resize(int width, int height)
156 {
157 Q_D(QWindowsDirect2DBitmap);
158 return d->resize(width, height);
159 }
160
fromImage(const QImage & image,Qt::ImageConversionFlags flags)161 bool QWindowsDirect2DBitmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
162 {
163 Q_D(QWindowsDirect2DBitmap);
164
165 QImage converted = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
166 return d->resize(converted.width(), converted.height(),
167 converted.constBits(), converted.bytesPerLine());
168 }
169
bitmap() const170 ID2D1Bitmap1* QWindowsDirect2DBitmap::bitmap() const
171 {
172 Q_D(const QWindowsDirect2DBitmap);
173 return d->bitmap.Get();
174 }
175
deviceContext() const176 QWindowsDirect2DDeviceContext *QWindowsDirect2DBitmap::deviceContext() const
177 {
178 Q_D(const QWindowsDirect2DBitmap);
179 return d->deviceContext.data();
180 }
181
fill(const QColor & color)182 void QWindowsDirect2DBitmap::fill(const QColor &color)
183 {
184 Q_D(QWindowsDirect2DBitmap);
185
186 d->deviceContext->begin();
187 d->deviceContext->get()->Clear(to_d2d_color_f(color));
188 d->deviceContext->end();
189 }
190
toImage(const QRect & rect)191 QImage QWindowsDirect2DBitmap::toImage(const QRect &rect)
192 {
193 Q_D(QWindowsDirect2DBitmap);
194 return d->toImage(rect);
195 }
196
size() const197 QSize QWindowsDirect2DBitmap::size() const
198 {
199 Q_D(const QWindowsDirect2DBitmap);
200
201 D2D1_SIZE_U size = d->bitmap->GetPixelSize();
202 return QSize(int(size.width), int(size.height));
203 }
204
205 QT_END_NAMESPACE
206