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 <opengl/win/gdiimpl.hxx>
32 #include <sal/log.hxx>
33 #include <o3tl/temporary.hxx>
35 HBITMAP
WinSalVirtualDevice::ImplCreateVirDevBitmap(HDC hDC
, long nDX
, long nDY
, sal_uInt16 nBitCount
, void **ppData
)
41 hBitmap
= CreateBitmap( static_cast<int>(nDX
), static_cast<int>(nDY
), 1, 1, nullptr );
42 SAL_WARN_IF( !hBitmap
, "vcl", "CreateBitmap failed: " << WindowsErrorString( GetLastError() ) );
48 nBitCount
= static_cast<WORD
>(GetDeviceCaps(hDC
, BITSPIXEL
));
50 // #146839# Don't use CreateCompatibleBitmap() - there seem to
51 // be built-in limits for those HBITMAPs, at least this fails
52 // rather often on large displays/multi-monitor setups.
53 BITMAPINFO aBitmapInfo
;
54 aBitmapInfo
.bmiHeader
.biSize
= sizeof( BITMAPINFOHEADER
);
55 aBitmapInfo
.bmiHeader
.biWidth
= nDX
;
56 aBitmapInfo
.bmiHeader
.biHeight
= nDY
;
57 aBitmapInfo
.bmiHeader
.biPlanes
= 1;
58 aBitmapInfo
.bmiHeader
.biBitCount
= nBitCount
;
59 aBitmapInfo
.bmiHeader
.biCompression
= BI_RGB
;
60 aBitmapInfo
.bmiHeader
.biSizeImage
= 0;
61 aBitmapInfo
.bmiHeader
.biXPelsPerMeter
= 0;
62 aBitmapInfo
.bmiHeader
.biYPelsPerMeter
= 0;
63 aBitmapInfo
.bmiHeader
.biClrUsed
= 0;
64 aBitmapInfo
.bmiHeader
.biClrImportant
= 0;
66 hBitmap
= CreateDIBSection( hDC
, &aBitmapInfo
,
67 DIB_RGB_COLORS
, ppData
, nullptr,
69 SAL_WARN_IF( !hBitmap
, "vcl", "CreateDIBSection failed: " << WindowsErrorString( GetLastError() ) );
75 std::unique_ptr
<SalVirtualDevice
> WinSalInstance::CreateVirtualDevice( SalGraphics
* pSGraphics
,
78 const SystemGraphicsData
* pData
)
80 WinSalGraphics
* pGraphics
= static_cast<WinSalGraphics
*>(pSGraphics
);
85 hDC
= (pData
->hDC
) ? pData
->hDC
: GetDC(pData
->hWnd
);
88 nDX
= GetDeviceCaps( hDC
, HORZRES
);
89 nDY
= GetDeviceCaps( hDC
, VERTRES
);
99 hDC
= CreateCompatibleDC( pGraphics
->getHDC() );
100 SAL_WARN_IF( !hDC
, "vcl", "CreateCompatibleDC failed: " << WindowsErrorString( GetLastError() ) );
106 sal_uInt16 nBitCount
= (eFormat
== DeviceFormat::BITMASK
) ? 1 : 0;
108 HBITMAP hBmp
= nullptr;
111 // #124826# continue even if hBmp could not be created
112 // if we would return a failure in this case, the process
113 // would terminate which is not required
114 hBmp
= WinSalVirtualDevice::ImplCreateVirDevBitmap(pGraphics
->getHDC(),
116 &o3tl::temporary
<void*>(nullptr));
119 const bool bForeignDC
= pData
!= nullptr && pData
->hDC
!= nullptr;
120 const SalData
* pSalData
= GetSalData();
122 WinSalVirtualDevice
* pVDev
= new WinSalVirtualDevice(hDC
, hBmp
, nBitCount
,
123 bForeignDC
, nDX
, nDY
);
125 WinSalGraphics
* pVirGraphics
= new WinSalGraphics(WinSalGraphics::VIRTUAL_DEVICE
,
126 pGraphics
->isScreen(), nullptr, pVDev
);
128 // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL()
129 pVirGraphics
->SetLayout( SalLayoutFlags::NONE
);
130 pVirGraphics
->setHDC(hDC
);
132 if ( pSalData
->mhDitherPal
&& pVirGraphics
->isScreen() )
134 pVirGraphics
->setDefPal(SelectPalette( hDC
, pSalData
->mhDitherPal
, TRUE
));
135 RealizePalette( hDC
);
138 pVirGraphics
->InitGraphics();
139 pVDev
->setGraphics(pVirGraphics
);
141 return std::unique_ptr
<SalVirtualDevice
>(pVDev
);
144 WinSalVirtualDevice::WinSalVirtualDevice(HDC hDC
, HBITMAP hBMP
, sal_uInt16 nBitCount
, bool bForeignDC
, long nWidth
, long nHeight
)
145 : mhLocalDC(hDC
), // HDC or 0 for Cache Device
146 mhBmp(hBMP
), // Memory Bitmap
147 mnBitCount(nBitCount
), // BitCount (0 or 1)
148 mbGraphics(false), // is Graphics used
149 mbForeignDC(bForeignDC
), // uses a foreign DC instead of a bitmap
155 mhDefBmp
= SelectBitmap(hDC
, hBMP
);
159 // insert VirDev into list of virtual devices
160 SalData
* pSalData
= GetSalData();
161 mpNext
= pSalData
->mpFirstVD
;
162 pSalData
->mpFirstVD
= this;
165 WinSalVirtualDevice::~WinSalVirtualDevice()
167 // remove VirDev from list of virtual devices
168 SalData
* pSalData
= GetSalData();
169 WinSalVirtualDevice
** ppVirDev
= &pSalData
->mpFirstVD
;
170 for(; (*ppVirDev
!= this) && *ppVirDev
; ppVirDev
= &(*ppVirDev
)->mpNext
);
175 if( mpGraphics
->getDefPal() )
176 SelectPalette( mpGraphics
->getHDC(), mpGraphics
->getDefPal(), TRUE
);
177 mpGraphics
->DeInitGraphics();
179 SelectBitmap( mpGraphics
->getHDC(), mhDefBmp
);
181 DeleteDC( mpGraphics
->getHDC() );
184 SalGraphics
* WinSalVirtualDevice::AcquireGraphics()
192 return mpGraphics
.get();
195 void WinSalVirtualDevice::ReleaseGraphics( SalGraphics
* )
200 bool WinSalVirtualDevice::SetSize( long nDX
, long nDY
)
202 if( mbForeignDC
|| !mhBmp
)
205 HBITMAP hNewBmp
= ImplCreateVirDevBitmap(getHDC(), nDX
, nDY
, mnBitCount
,
206 &o3tl::temporary
<void*>(nullptr));
217 SelectBitmap(getHDC(), hNewBmp
);
218 mhBmp
.reset(hNewBmp
);
222 WinOpenGLSalGraphicsImpl
*pImpl
;
223 pImpl
= dynamic_cast< WinOpenGLSalGraphicsImpl
* >(mpGraphics
->GetImpl());
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */