1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <comphelper/windowserrorstring.hxx>
24 #include <vcl/sysdata.hxx>
26 #include <win/wincomp.hxx>
27 #include <win/saldata.hxx>
28 #include <win/salinst.h>
29 #include <win/salgdi.h>
30 #include <win/salvd.h>
31 #include <sal/log.hxx>
32 #include <o3tl/temporary.hxx>
34 HBITMAP
WinSalVirtualDevice::ImplCreateVirDevBitmap(HDC hDC
, tools::Long nDX
, tools::Long nDY
, sal_uInt16 nBitCount
, void **ppData
)
40 hBitmap
= CreateBitmap( static_cast<int>(nDX
), static_cast<int>(nDY
), 1, 1, nullptr );
41 SAL_WARN_IF( !hBitmap
, "vcl", "CreateBitmap failed: " << WindowsErrorString( GetLastError() ) );
47 nBitCount
= static_cast<WORD
>(GetDeviceCaps(hDC
, BITSPIXEL
));
49 // #146839# Don't use CreateCompatibleBitmap() - there seem to
50 // be built-in limits for those HBITMAPs, at least this fails
51 // rather often on large displays/multi-monitor setups.
52 BITMAPINFO aBitmapInfo
;
53 aBitmapInfo
.bmiHeader
.biSize
= sizeof( BITMAPINFOHEADER
);
54 aBitmapInfo
.bmiHeader
.biWidth
= nDX
;
55 aBitmapInfo
.bmiHeader
.biHeight
= nDY
;
56 aBitmapInfo
.bmiHeader
.biPlanes
= 1;
57 aBitmapInfo
.bmiHeader
.biBitCount
= nBitCount
;
58 aBitmapInfo
.bmiHeader
.biCompression
= BI_RGB
;
59 aBitmapInfo
.bmiHeader
.biSizeImage
= 0;
60 aBitmapInfo
.bmiHeader
.biXPelsPerMeter
= 0;
61 aBitmapInfo
.bmiHeader
.biYPelsPerMeter
= 0;
62 aBitmapInfo
.bmiHeader
.biClrUsed
= 0;
63 aBitmapInfo
.bmiHeader
.biClrImportant
= 0;
65 hBitmap
= CreateDIBSection( hDC
, &aBitmapInfo
,
66 DIB_RGB_COLORS
, ppData
, nullptr,
68 SAL_WARN_IF( !hBitmap
, "vcl", "CreateDIBSection failed: " << WindowsErrorString( GetLastError() ) );
74 std::unique_ptr
<SalVirtualDevice
> WinSalInstance::CreateVirtualDevice( SalGraphics
& rSGraphics
,
75 tools::Long
&nDX
, tools::Long
&nDY
,
76 DeviceFormat
/*eFormat*/,
77 const SystemGraphicsData
* pData
)
79 WinSalGraphics
& rGraphics
= static_cast<WinSalGraphics
&>(rSGraphics
);
84 hDC
= (pData
->hDC
) ? pData
->hDC
: GetDC(pData
->hWnd
);
87 nDX
= GetDeviceCaps( hDC
, HORZRES
);
88 nDY
= GetDeviceCaps( hDC
, VERTRES
);
98 hDC
= CreateCompatibleDC( rGraphics
.getHDC() );
99 SAL_WARN_IF( !hDC
, "vcl", "CreateCompatibleDC failed: " << WindowsErrorString( GetLastError() ) );
105 sal_uInt16 nBitCount
= 0;
106 HBITMAP hBmp
= nullptr;
109 // #124826# continue even if hBmp could not be created
110 // if we would return a failure in this case, the process
111 // would terminate which is not required
112 hBmp
= WinSalVirtualDevice::ImplCreateVirDevBitmap(rGraphics
.getHDC(),
114 &o3tl::temporary
<void*>(nullptr));
117 const bool bForeignDC
= pData
!= nullptr && pData
->hDC
!= nullptr;
118 const SalData
* pSalData
= GetSalData();
120 WinSalVirtualDevice
* pVDev
= new WinSalVirtualDevice(hDC
, hBmp
, nBitCount
,
121 bForeignDC
, nDX
, nDY
);
123 WinSalGraphics
* pVirGraphics
= new WinSalGraphics(WinSalGraphics::VIRTUAL_DEVICE
,
124 rGraphics
.isScreen(), nullptr, pVDev
);
126 // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL()
127 pVirGraphics
->SetLayout( SalLayoutFlags::NONE
);
128 pVirGraphics
->setHDC(hDC
);
130 if ( pSalData
->mhDitherPal
&& pVirGraphics
->isScreen() )
132 pVirGraphics
->setPalette(pSalData
->mhDitherPal
);
133 RealizePalette( hDC
);
136 pVDev
->setGraphics(pVirGraphics
);
138 return std::unique_ptr
<SalVirtualDevice
>(pVDev
);
141 WinSalVirtualDevice::WinSalVirtualDevice(HDC hDC
, HBITMAP hBMP
, sal_uInt16 nBitCount
, bool bForeignDC
, tools::Long nWidth
, tools::Long nHeight
)
142 : mhLocalDC(hDC
), // HDC or 0 for Cache Device
143 mhBmp(hBMP
), // Memory Bitmap
144 mnBitCount(nBitCount
), // BitCount (0 or 1)
145 mbGraphics(false), // is Graphics used
146 mbForeignDC(bForeignDC
), // uses a foreign DC instead of a bitmap
152 mhDefBmp
= SelectBitmap(hDC
, hBMP
);
156 // insert VirDev into list of virtual devices
157 SalData
* pSalData
= GetSalData();
158 mpNext
= pSalData
->mpFirstVD
;
159 pSalData
->mpFirstVD
= this;
162 WinSalVirtualDevice::~WinSalVirtualDevice()
164 // remove VirDev from list of virtual devices
165 SalData
* pSalData
= GetSalData();
166 WinSalVirtualDevice
** ppVirDev
= &pSalData
->mpFirstVD
;
167 for(; (*ppVirDev
!= this) && *ppVirDev
; ppVirDev
= &(*ppVirDev
)->mpNext
);
171 HDC hDC
= mpGraphics
->getHDC();
172 // restore the mpGraphics' original HDC values, so the HDC can be deleted in the !mbForeignDC case
173 mpGraphics
->setHDC(nullptr);
176 SelectBitmap(hDC
, mhDefBmp
);
181 SalGraphics
* WinSalVirtualDevice::AcquireGraphics()
189 return mpGraphics
.get();
192 void WinSalVirtualDevice::ReleaseGraphics( SalGraphics
* )
197 bool WinSalVirtualDevice::SetSize( tools::Long nDX
, tools::Long nDY
)
199 if( mbForeignDC
|| !mhBmp
)
202 HBITMAP hNewBmp
= ImplCreateVirDevBitmap(getHDC(), nDX
, nDY
, mnBitCount
,
203 &o3tl::temporary
<void*>(nullptr));
214 SelectBitmap(getHDC(), hNewBmp
);
215 mhBmp
.reset(hNewBmp
);
220 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */