vcl/headless/svpinst.cxx | 18 +++- vcl/inc/headless/svpinst.hxx | 11 ++ vcl/inc/osx/salinst.h | 6 + vcl/inc/qt5/QtInstance.hxx | 6 + vcl/inc/quartz/salvd.h | 3 vcl/inc/salinst.hxx | 12 ++ vcl/inc/skia/x11/salvd.hxx | 4 vcl/inc/unx/gtk/gtkinst.hxx | 6 + vcl/inc/unx/salinst.h | 10 +- vcl/inc/unx/salvd.h | 4 vcl/inc/win/salinst.h | 6 + vcl/qt5/QtInstance.cxx | 27 +++++- vcl/quartz/salvd.cxx | 170 +++++++++++++++++++++++------------------- vcl/skia/x11/salvd.cxx | 20 ++++ vcl/source/gdi/virdev.cxx | 7 + vcl/unx/generic/gdi/salvd.cxx | 123 +++++++++++++++++++++--------- vcl/unx/gtk3/gtkinst.cxx | 18 +++- vcl/win/gdi/salvd.cxx | 83 +++++++++++++------- 18 files changed, 365 insertions(+), 169 deletions(-)
New commits: commit a46c265051af9b383c928914087d1e91025c2d2f Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Mon Feb 3 15:29:57 2025 +0200 Commit: Noel Grandin <noelgran...@gmail.com> CommitDate: Mon Feb 3 21:56:09 2025 +0100 split CreateVirtualDevice into two methods because I need to make it more complicated in an upcoming patch, and this is already complicated. Change-Id: I920adc8729e53672a370c9778aa2b8a6b907ad50 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181046 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx index 54ac078f83f0..d2a4941321e5 100644 --- a/vcl/headless/svpinst.cxx +++ b/vcl/headless/svpinst.cxx @@ -197,10 +197,22 @@ void SvpSalInstance::DestroyObject( SalObject* pObject ) #ifndef IOS +std::unique_ptr<SalVirtualDevice> SvpSalInstance::CreateVirtualDevice(SalGraphics& rGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat /*eFormat*/) +{ + SvpSalGraphics *pSvpSalGraphics = dynamic_cast<SvpSalGraphics*>(&rGraphics); + assert(pSvpSalGraphics); + std::unique_ptr<SalVirtualDevice> xNew(new SvpSalVirtualDevice(pSvpSalGraphics->getSurface(), /*pPreExistingTarget*/nullptr)); + if (!xNew->SetSize(nDX, nDY)) + xNew.reset(); + return xNew; +} + std::unique_ptr<SalVirtualDevice> SvpSalInstance::CreateVirtualDevice(SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, DeviceFormat /*eFormat*/, - const SystemGraphicsData* pGd) + const SystemGraphicsData& rGd) { SvpSalGraphics *pSvpSalGraphics = dynamic_cast<SvpSalGraphics*>(&rGraphics); assert(pSvpSalGraphics); @@ -208,10 +220,10 @@ std::unique_ptr<SalVirtualDevice> SvpSalInstance::CreateVirtualDevice(SalGraphic // tdf#127529 normally pPreExistingTarget is null and we are a true virtualdevice drawing to a backing buffer. // Occasionally, for canvas/slideshow, pPreExistingTarget is pre-provided as a hack to use the vcl drawing // apis to render onto a preexisting cairo surface. The necessity for that precedes the use of cairo in vcl proper - cairo_surface_t* pPreExistingTarget = pGd ? static_cast<cairo_surface_t*>(pGd->pSurface) : nullptr; + cairo_surface_t* pPreExistingTarget = static_cast<cairo_surface_t*>(rGd.pSurface); #else //ANDROID case - (void)pGd; + (void)rGd; cairo_surface_t* pPreExistingTarget = nullptr; #endif std::unique_ptr<SalVirtualDevice> xNew(new SvpSalVirtualDevice(pSvpSalGraphics->getSurface(), pPreExistingTarget)); diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx index f3d9205a8981..2edd71dd78c7 100644 --- a/vcl/inc/headless/svpinst.hxx +++ b/vcl/inc/headless/svpinst.hxx @@ -136,12 +136,19 @@ public: // VirtualDevice // nDX and nDY in Pixel - // nBitCount: 0 == Default(=as window) / 1 == Mono + SAL_DLLPRIVATE virtual std::unique_ptr<SalVirtualDevice> + CreateVirtualDevice( SalGraphics& rGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat ) override; + + // VirtualDevice + // nDX and nDY in Pixel // pData allows for using a system dependent graphics or device context SAL_DLLPRIVATE virtual std::unique_ptr<SalVirtualDevice> CreateVirtualDevice( SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, - DeviceFormat eFormat, const SystemGraphicsData *pData = nullptr ) override; + DeviceFormat eFormat, + const SystemGraphicsData& rData ) override; // Printer // pSetupData->mpDriverData can be 0 diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h index 8811fa3c9c72..dbc9066d373d 100644 --- a/vcl/inc/osx/salinst.h +++ b/vcl/inc/osx/salinst.h @@ -106,11 +106,15 @@ public: virtual SalObject* CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, bool bShow ) override; virtual void DestroyObject( SalObject* pObject ) override; + virtual std::unique_ptr<SalVirtualDevice> + CreateVirtualDevice( SalGraphics& rGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat ) override; virtual std::unique_ptr<SalVirtualDevice> CreateVirtualDevice( SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, - const SystemGraphicsData *pData = nullptr ) override; + const SystemGraphicsData& rData ) override; virtual SalInfoPrinter* CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, ImplJobSetup* pSetupData ) override; virtual void DestroyInfoPrinter( SalInfoPrinter* pPrinter ) override; diff --git a/vcl/inc/qt5/QtInstance.hxx b/vcl/inc/qt5/QtInstance.hxx index cf2cec53f762..90c32bf06bd5 100644 --- a/vcl/inc/qt5/QtInstance.hxx +++ b/vcl/inc/qt5/QtInstance.hxx @@ -124,9 +124,13 @@ public: bool bShow) override; virtual void DestroyObject(SalObject* pObject) override; + virtual std::unique_ptr<SalVirtualDevice> CreateVirtualDevice(SalGraphics& rGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat) override; + virtual std::unique_ptr<SalVirtualDevice> CreateVirtualDevice(SalGraphics& rGraphics, tools::Long& nDX, tools::Long& nDY, - DeviceFormat eFormat, const SystemGraphicsData* pData = nullptr) override; + DeviceFormat eFormat, const SystemGraphicsData& rData) override; virtual SalInfoPrinter* CreateInfoPrinter(SalPrinterQueueInfo* pQueueInfo, ImplJobSetup* pSetupData) override; diff --git a/vcl/inc/quartz/salvd.h b/vcl/inc/quartz/salvd.h index 939bd041cee1..941ffe9df3ca 100644 --- a/vcl/inc/quartz/salvd.h +++ b/vcl/inc/quartz/salvd.h @@ -52,7 +52,8 @@ private: void Destroy(); public: - AquaSalVirtualDevice( AquaSalGraphics* pGraphic, tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, const SystemGraphicsData *pData ); + AquaSalVirtualDevice( AquaSalGraphics* pGraphic, tools::Long nDX, tools::Long nDY, DeviceFormat eFormat ); + AquaSalVirtualDevice( AquaSalGraphics* pGraphic, tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, const SystemGraphicsData& rData ); virtual ~AquaSalVirtualDevice() override; virtual SalGraphics* AcquireGraphics() override; diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx index b8549b23fc5f..ee67654830d3 100644 --- a/vcl/inc/salinst.hxx +++ b/vcl/inc/salinst.hxx @@ -106,14 +106,22 @@ public: // VirtualDevice // nDX and nDY in pixels - // nBitCount: 0 == default(=as window) / 1 == mono // pData allows for using a system dependent graphics or device context, // if a system context is passed in nDX and nDY are updated to reflect // its size; otherwise these remain unchanged. + virtual std::unique_ptr<SalVirtualDevice> + CreateVirtualDevice( SalGraphics& rGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat ) = 0; + + // VirtualDevice + // nDX and nDY in pixels + // pData allows for using a system dependent graphics or device context, + // nDX and nDY are updated to reflect its size; otherwise these remain unchanged. virtual std::unique_ptr<SalVirtualDevice> CreateVirtualDevice( SalGraphics& rGraphics, tools::Long &rDX, tools::Long &rDY, - DeviceFormat eFormat, const SystemGraphicsData *pData = nullptr ) = 0; + DeviceFormat eFormat, const SystemGraphicsData& rData ) = 0; // Printer // pSetupData->mpDriverData can be 0 diff --git a/vcl/inc/skia/x11/salvd.hxx b/vcl/inc/skia/x11/salvd.hxx index 9dc952350f7b..02babb2366e6 100644 --- a/vcl/inc/skia/x11/salvd.hxx +++ b/vcl/inc/skia/x11/salvd.hxx @@ -24,7 +24,9 @@ class X11SkiaSalVirtualDevice final : public SalVirtualDevice public: X11SkiaSalVirtualDevice(const SalGraphics& rGraphics, tools::Long nDX, tools::Long nDY, - const SystemGraphicsData* pData, + std::unique_ptr<X11SalGraphics> pNewGraphics); + X11SkiaSalVirtualDevice(const SalGraphics& rGraphics, tools::Long nDX, tools::Long nDY, + const SystemGraphicsData& rData, std::unique_ptr<X11SalGraphics> pNewGraphics); virtual ~X11SkiaSalVirtualDevice() override; diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx index 1f9e328bb8d8..319622abb0ba 100644 --- a/vcl/inc/unx/gtk/gtkinst.hxx +++ b/vcl/inc/unx/gtk/gtkinst.hxx @@ -263,11 +263,15 @@ public: virtual std::unique_ptr<SalMenuItem> CreateMenuItem( const SalItemParams& ) override; virtual SalTimer* CreateSalTimer() override; virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService) override; + virtual std::unique_ptr<SalVirtualDevice> + CreateVirtualDevice( SalGraphics&, + tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat ) override; virtual std::unique_ptr<SalVirtualDevice> CreateVirtualDevice( SalGraphics&, tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, - const SystemGraphicsData* = nullptr ) override; + const SystemGraphicsData& ) override; virtual std::shared_ptr<SalBitmap> CreateSalBitmap() override; virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents) override; diff --git a/vcl/inc/unx/salinst.h b/vcl/inc/unx/salinst.h index e8f24e255c91..00616e2a5d44 100644 --- a/vcl/inc/unx/salinst.h +++ b/vcl/inc/unx/salinst.h @@ -50,13 +50,19 @@ public: virtual void DestroyObject( SalObject* pObject ) override; /// Gtk vclplug needs to pass GtkSalGraphics to X11SalVirtualDevice, so create it, and pass as pNewGraphics. + static std::unique_ptr<SalVirtualDevice> CreateX11VirtualDevice(const SalGraphics& rGraphics, tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat, std::unique_ptr<X11SalGraphics> pNewGraphics); static std::unique_ptr<SalVirtualDevice> CreateX11VirtualDevice(const SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, - DeviceFormat eFormat, const SystemGraphicsData* pData, std::unique_ptr<X11SalGraphics> pNewGraphics); + DeviceFormat eFormat, const SystemGraphicsData& rData, std::unique_ptr<X11SalGraphics> pNewGraphics); + virtual std::unique_ptr<SalVirtualDevice> + CreateVirtualDevice( SalGraphics& rGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat ) override; virtual std::unique_ptr<SalVirtualDevice> CreateVirtualDevice( SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, - DeviceFormat eFormat, const SystemGraphicsData *pData = nullptr ) override; + DeviceFormat eFormat, const SystemGraphicsData& rData ) override; virtual void PostPrintersChanged() override; virtual std::unique_ptr<GenPspGraphics> CreatePrintGraphics() override; diff --git a/vcl/inc/unx/salvd.h b/vcl/inc/unx/salvd.h index f85d5363589d..ca5a73506aad 100644 --- a/vcl/inc/unx/salvd.h +++ b/vcl/inc/unx/salvd.h @@ -50,8 +50,10 @@ class X11SalVirtualDevice final : public SalVirtualDevice bool m_bOwnsSurface; // nearly always true, except for edge case of tdf#127529 public: + X11SalVirtualDevice(const SalGraphics& rGraphics, tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat, std::unique_ptr<X11SalGraphics> pNewGraphics); X11SalVirtualDevice(const SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, - DeviceFormat eFormat, const SystemGraphicsData *pData, std::unique_ptr<X11SalGraphics> pNewGraphics); + DeviceFormat eFormat, const SystemGraphicsData& rData, std::unique_ptr<X11SalGraphics> pNewGraphics); virtual ~X11SalVirtualDevice() override; diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h index cc02c8bad4a2..0bd3026619c9 100644 --- a/vcl/inc/win/salinst.h +++ b/vcl/inc/win/salinst.h @@ -49,10 +49,14 @@ public: virtual void DestroyFrame( SalFrame* pFrame ) override; virtual SalObject* CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, bool bShow ) override; virtual void DestroyObject( SalObject* pObject ) override; + virtual std::unique_ptr<SalVirtualDevice> + CreateVirtualDevice( SalGraphics& rGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat ) override; virtual std::unique_ptr<SalVirtualDevice> CreateVirtualDevice( SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, - DeviceFormat eFormat, const SystemGraphicsData *pData = nullptr ) override; + DeviceFormat eFormat, const SystemGraphicsData& rData ) override; virtual SalInfoPrinter* CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, ImplJobSetup* pSetupData ) override; virtual void DestroyInfoPrinter( SalInfoPrinter* pPrinter ) override; diff --git a/vcl/qt5/QtInstance.cxx b/vcl/qt5/QtInstance.cxx index aa1c369fbe2d..2a206aaf6a2f 100644 --- a/vcl/qt5/QtInstance.cxx +++ b/vcl/qt5/QtInstance.cxx @@ -388,17 +388,38 @@ void QtInstance::DestroyObject(SalObject* pObject) } } +std::unique_ptr<SalVirtualDevice> QtInstance::CreateVirtualDevice(SalGraphics& rGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat /*eFormat*/) +{ + if (m_bUseCairo) + { + SvpSalGraphics* pSvpSalGraphics = dynamic_cast<QtSvpGraphics*>(&rGraphics); + assert(pSvpSalGraphics); + // tdf#127529 see SvpSalInstance::CreateVirtualDevice for the rare case of a non-null pPreExistingTarget + std::unique_ptr<SalVirtualDevice> pVD( + new QtSvpVirtualDevice(pSvpSalGraphics->getSurface(), /*pPreExistingTarget*/ nullptr)); + pVD->SetSize(nDX, nDY); + return pVD; + } + else + { + std::unique_ptr<SalVirtualDevice> pVD(new QtVirtualDevice(/*scale*/ 1)); + pVD->SetSize(nDX, nDY); + return pVD; + } +} + std::unique_ptr<SalVirtualDevice> QtInstance::CreateVirtualDevice(SalGraphics& rGraphics, tools::Long& nDX, tools::Long& nDY, - DeviceFormat /*eFormat*/, const SystemGraphicsData* pGd) + DeviceFormat /*eFormat*/, const SystemGraphicsData& rGd) { if (m_bUseCairo) { SvpSalGraphics* pSvpSalGraphics = dynamic_cast<QtSvpGraphics*>(&rGraphics); assert(pSvpSalGraphics); // tdf#127529 see SvpSalInstance::CreateVirtualDevice for the rare case of a non-null pPreExistingTarget - cairo_surface_t* pPreExistingTarget - = pGd ? static_cast<cairo_surface_t*>(pGd->pSurface) : nullptr; + cairo_surface_t* pPreExistingTarget = static_cast<cairo_surface_t*>(rGd.pSurface); std::unique_ptr<SalVirtualDevice> pVD( new QtSvpVirtualDevice(pSvpSalGraphics->getSurface(), pPreExistingTarget)); pVD->SetSize(nDX, nDY); diff --git a/vcl/quartz/salvd.cxx b/vcl/quartz/salvd.cxx index 4e0c295a17f4..69f18473fb91 100644 --- a/vcl/quartz/salvd.cxx +++ b/vcl/quartz/salvd.cxx @@ -37,113 +37,131 @@ #include <quartz/salvd.h> #include <quartz/utils.h> +std::unique_ptr<SalVirtualDevice> AquaSalInstance::CreateVirtualDevice( SalGraphics& rGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat ) +{ + // #i92075# can be called first in a thread + SalData::ensureThreadAutoreleasePool(); + +#ifdef IOS + std::unique_ptr<SalVirtualDevice> pNew(new AquaSalVirtualDevice( NULL, nDX, nDY, eFormat, NULL )); + pNew->SetSize( nDX, nDY ); + return pNew; +#else + return std::unique_ptr<SalVirtualDevice>(new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >(&rGraphics), + nDX, nDY, eFormat )); +#endif +} + std::unique_ptr<SalVirtualDevice> AquaSalInstance::CreateVirtualDevice( SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, - const SystemGraphicsData *pData ) + const SystemGraphicsData& rData ) { // #i92075# can be called first in a thread SalData::ensureThreadAutoreleasePool(); #ifdef IOS - if( pData ) - { - return std::unique_ptr<SalVirtualDevice>(new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >(&rGraphics), - nDX, nDY, eFormat, pData )); - } - else - { - std::unique_ptr<SalVirtualDevice> pNew(new AquaSalVirtualDevice( NULL, nDX, nDY, eFormat, NULL )); - pNew->SetSize( nDX, nDY ); - return pNew; - } + return std::unique_ptr<SalVirtualDevice>(new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >(&rGraphics), + nDX, nDY, eFormat, rData )); #else return std::unique_ptr<SalVirtualDevice>(new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >(&rGraphics), - nDX, nDY, eFormat, pData )); + nDX, nDY, eFormat, rData )); #endif } AquaSalVirtualDevice::AquaSalVirtualDevice( - AquaSalGraphics* pGraphic, tools::Long &nDX, tools::Long &nDY, - DeviceFormat eFormat, const SystemGraphicsData *pData ) + AquaSalGraphics* pGraphic, tools::Long nDX, tools::Long nDY, + DeviceFormat eFormat ) : mbGraphicsUsed( false ) , mnBitmapDepth( 0 ) , mnWidth(0) , mnHeight(0) { SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::AquaSalVirtualDevice() this=" << this - << " size=(" << nDX << "x" << nDY << ") bitcount=" << static_cast<int>(eFormat) << - " pData=" << pData << " context=" << (pData ? pData->rCGContext : nullptr) ); + << " size=(" << nDX << "x" << nDY << ") bitcount=" << static_cast<int>(eFormat) ); + + // create empty new virtual device - if( pGraphic && pData && pData->rCGContext ) + mbForeignContext = false; // the mxContext is created within VCL + mpGraphics = new AquaSalGraphics(); // never fails + switch (eFormat) { - // Create virtual device based on existing SystemGraphicsData - // We ignore nDx and nDY, as the desired size comes from the SystemGraphicsData. - // the mxContext is from pData (what "mxContext"? there is no such field anywhere in vcl;) - mbForeignContext = true; - mpGraphics = new AquaSalGraphics( /*pGraphic*/ ); - if (nDX == 0) - { - nDX = 1; - } - if (nDY == 0) - { - nDY = 1; - } - maLayer.set(CGLayerCreateWithContext(pData->rCGContext, CGSizeMake(nDX, nDY), nullptr)); - // Interrogate the context as to its real size - if (maLayer.isSet()) - { - const CGSize aSize = CGLayerGetSize(maLayer.get()); - nDX = static_cast<tools::Long>(aSize.width); - nDY = static_cast<tools::Long>(aSize.height); - } - else +#ifdef IOS + case DeviceFormat::GRAYSCALE: + mnBitmapDepth = 8; + break; +#endif + default: + mnBitmapDepth = 0; + break; + } +#ifdef MACOSX + // inherit resolution from reference device + if( pGraphic ) + { + AquaSalFrame* pFrame = pGraphic->getGraphicsFrame(); + if( pFrame && AquaSalFrame::isAlive( pFrame ) ) { - nDX = 0; - nDY = 0; + mpGraphics->setGraphicsFrame( pFrame ); + mpGraphics->copyResolution( *pGraphic ); } + } +#endif + if( nDX && nDY ) + { + SetSize( nDX, nDY ); + } + // NOTE: if SetSize does not succeed, we just ignore the nDX and nDY +} - mpGraphics->SetVirDevGraphics(this, maLayer, pData->rCGContext); +AquaSalVirtualDevice::AquaSalVirtualDevice( + AquaSalGraphics* pGraphic, tools::Long &nDX, tools::Long &nDY, + DeviceFormat eFormat, const SystemGraphicsData& rData ) + : mbGraphicsUsed( false ) + , mnBitmapDepth( 0 ) + , mnWidth(0) + , mnHeight(0) +{ + SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::AquaSalVirtualDevice() this=" << this + << " size=(" << nDX << "x" << nDY << ") bitcount=" << static_cast<int>(eFormat) << + " rData=" << &rData << " context=" << rData.rCGContext ); - SAL_INFO("vcl.virdev", "AquaSalVirtualDevice::AquaSalVirtualDevice() this=" << this << - " (" << nDX << "x" << nDY << ") mbForeignContext=" << (mbForeignContext ? "YES" : "NO")); + assert(pGraphic); + assert(rData.rCGContext); + // Create virtual device based on existing SystemGraphicsData + // We ignore nDx and nDY, as the desired size comes from the SystemGraphicsData. + // the mxContext is from pData (what "mxContext"? there is no such field anywhere in vcl;) + mbForeignContext = true; + mpGraphics = new AquaSalGraphics( /*pGraphic*/ ); + if (nDX == 0) + { + nDX = 1; + } + if (nDY == 0) + { + nDY = 1; + } + maLayer.set(CGLayerCreateWithContext(rData.rCGContext, CGSizeMake(nDX, nDY), nullptr)); + // Interrogate the context as to its real size + if (maLayer.isSet()) + { + const CGSize aSize = CGLayerGetSize(maLayer.get()); + nDX = static_cast<tools::Long>(aSize.width); + nDY = static_cast<tools::Long>(aSize.height); } else { - // create empty new virtual device - mbForeignContext = false; // the mxContext is created within VCL - mpGraphics = new AquaSalGraphics(); // never fails - switch (eFormat) - { -#ifdef IOS - case DeviceFormat::GRAYSCALE: - mnBitmapDepth = 8; - break; -#endif - default: - mnBitmapDepth = 0; - break; - } -#ifdef MACOSX - // inherit resolution from reference device - if( pGraphic ) - { - AquaSalFrame* pFrame = pGraphic->getGraphicsFrame(); - if( pFrame && AquaSalFrame::isAlive( pFrame ) ) - { - mpGraphics->setGraphicsFrame( pFrame ); - mpGraphics->copyResolution( *pGraphic ); - } - } -#endif - if( nDX && nDY ) - { - SetSize( nDX, nDY ); - } - // NOTE: if SetSize does not succeed, we just ignore the nDX and nDY + nDX = 0; + nDY = 0; } + + mpGraphics->SetVirDevGraphics(this, maLayer, rData.rCGContext); + + SAL_INFO("vcl.virdev", "AquaSalVirtualDevice::AquaSalVirtualDevice() this=" << this << + " (" << nDX << "x" << nDY << ") mbForeignContext=" << (mbForeignContext ? "YES" : "NO")); } AquaSalVirtualDevice::~AquaSalVirtualDevice() diff --git a/vcl/skia/x11/salvd.cxx b/vcl/skia/x11/salvd.cxx index 8979f36d32b3..c128bae50413 100644 --- a/vcl/skia/x11/salvd.cxx +++ b/vcl/skia/x11/salvd.cxx @@ -30,7 +30,7 @@ void X11SalGraphics::Init(X11SkiaSalVirtualDevice* pDevice) } X11SkiaSalVirtualDevice::X11SkiaSalVirtualDevice(const SalGraphics& rGraphics, tools::Long nDX, - tools::Long nDY, const SystemGraphicsData* pData, + tools::Long nDY, std::unique_ptr<X11SalGraphics> pNewGraphics) : mpGraphics(std::move(pNewGraphics)) , mbGraphics(false) @@ -38,9 +38,23 @@ X11SkiaSalVirtualDevice::X11SkiaSalVirtualDevice(const SalGraphics& rGraphics, t { assert(mpGraphics); + mpDisplay = vcl_sal::getSalDisplay(GetGenericUnixSalData()); + mnXScreen = static_cast<const X11SalGraphics&>(rGraphics).GetScreenNumber(); + mnWidth = nDX; + mnHeight = nDY; + mpGraphics->Init(this); +} + +X11SkiaSalVirtualDevice::X11SkiaSalVirtualDevice(const SalGraphics& rGraphics, tools::Long nDX, + tools::Long nDY, + const SystemGraphicsData& /*rData*/, + std::unique_ptr<X11SalGraphics> pNewGraphics) + : mpGraphics(std::move(pNewGraphics)) + , mbGraphics(false) + , mnXScreen(0) +{ // TODO Check where a VirtualDevice is created from SystemGraphicsData - assert(pData == nullptr); - (void)pData; + assert(false); mpDisplay = vcl_sal::getSalDisplay(GetGenericUnixSalData()); mnXScreen = static_cast<const X11SalGraphics&>(rGraphics).GetScreenNumber(); diff --git a/vcl/source/gdi/virdev.cxx b/vcl/source/gdi/virdev.cxx index 6c44cb110fce..1d1ecc98ef27 100644 --- a/vcl/source/gdi/virdev.cxx +++ b/vcl/source/gdi/virdev.cxx @@ -154,7 +154,12 @@ void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev, (void)pOutDev->AcquireGraphics(); pGraphics = pOutDev->mpGraphics; if ( pGraphics ) - mpVirDev = pSVData->mpDefInst->CreateVirtualDevice(*pGraphics, nDX, nDY, meFormatAndAlpha, pData); + { + if (pData) + mpVirDev = pSVData->mpDefInst->CreateVirtualDevice(*pGraphics, nDX, nDY, meFormatAndAlpha, *pData); + else + mpVirDev = pSVData->mpDefInst->CreateVirtualDevice(*pGraphics, nDX, nDY, meFormatAndAlpha); + } else mpVirDev = nullptr; if ( !mpVirDev ) diff --git a/vcl/unx/generic/gdi/salvd.cxx b/vcl/unx/generic/gdi/salvd.cxx index 33ba19c95d59..52b87875d2e6 100644 --- a/vcl/unx/generic/gdi/salvd.cxx +++ b/vcl/unx/generic/gdi/salvd.cxx @@ -35,22 +35,41 @@ #include <cairo-xlib.h> std::unique_ptr<SalVirtualDevice> X11SalInstance::CreateX11VirtualDevice(const SalGraphics& rGraphics, - tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, const SystemGraphicsData *pData, + tools::Long nDX, tools::Long nDY, DeviceFormat eFormat, std::unique_ptr<X11SalGraphics> pNewGraphics) { assert(pNewGraphics); #if HAVE_FEATURE_SKIA if (SkiaHelper::isVCLSkiaEnabled()) - return std::unique_ptr<SalVirtualDevice>(new X11SkiaSalVirtualDevice(rGraphics, nDX, nDY, pData, std::move(pNewGraphics))); + return std::unique_ptr<SalVirtualDevice>(new X11SkiaSalVirtualDevice(rGraphics, nDX, nDY, std::move(pNewGraphics))); else #endif - return std::unique_ptr<SalVirtualDevice>(new X11SalVirtualDevice(rGraphics, nDX, nDY, eFormat, pData, std::move(pNewGraphics))); + return std::unique_ptr<SalVirtualDevice>(new X11SalVirtualDevice(rGraphics, nDX, nDY, eFormat, std::move(pNewGraphics))); +} + +std::unique_ptr<SalVirtualDevice> X11SalInstance::CreateX11VirtualDevice(const SalGraphics& rGraphics, + tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, const SystemGraphicsData& rData, + std::unique_ptr<X11SalGraphics> pNewGraphics) +{ + assert(pNewGraphics); +#if HAVE_FEATURE_SKIA + if (SkiaHelper::isVCLSkiaEnabled()) + return std::unique_ptr<SalVirtualDevice>(new X11SkiaSalVirtualDevice(rGraphics, nDX, nDY, rData, std::move(pNewGraphics))); + else +#endif + return std::unique_ptr<SalVirtualDevice>(new X11SalVirtualDevice(rGraphics, nDX, nDY, eFormat, rData, std::move(pNewGraphics))); } std::unique_ptr<SalVirtualDevice> X11SalInstance::CreateVirtualDevice(SalGraphics& rGraphics, - tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, const SystemGraphicsData *pData) + tools::Long nDX, tools::Long nDY, DeviceFormat eFormat) { - return CreateX11VirtualDevice(rGraphics, nDX, nDY, eFormat, pData, std::make_unique<X11SalGraphics>()); + return CreateX11VirtualDevice(rGraphics, nDX, nDY, eFormat, std::make_unique<X11SalGraphics>()); +} + +std::unique_ptr<SalVirtualDevice> X11SalInstance::CreateVirtualDevice(SalGraphics& rGraphics, + tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, const SystemGraphicsData& rData) +{ + return CreateX11VirtualDevice(rGraphics, nDX, nDY, eFormat, rData, std::make_unique<X11SalGraphics>()); } void X11SalGraphics::Init(X11SalVirtualDevice *pDevice, SalColormap* pColormap, bool bDeleteColormap) @@ -82,8 +101,8 @@ void X11SalGraphics::Init(X11SalVirtualDevice *pDevice, SalColormap* pColormap, mxImpl->UpdateX11GeometryProvider(); } -X11SalVirtualDevice::X11SalVirtualDevice(const SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, - DeviceFormat /*eFormat*/, const SystemGraphicsData *pData, +X11SalVirtualDevice::X11SalVirtualDevice(const SalGraphics& rGraphics, tools::Long nDX, tools::Long nDY, + DeviceFormat /*eFormat*/, std::unique_ptr<X11SalGraphics> pNewGraphics) : pGraphics_(std::move(pNewGraphics)), m_nXScreen(0), @@ -96,40 +115,68 @@ X11SalVirtualDevice::X11SalVirtualDevice(const SalGraphics& rGraphics, tools::Lo pDisplay_ = vcl_sal::getSalDisplay(GetGenericUnixSalData()); nDepth_ = nBitCount; - if( pData && pData->hDrawable != None ) + nDX_ = nDX; + nDY_ = nDY; + m_nXScreen = static_cast<const X11SalGraphics&>(rGraphics).GetScreenNumber(); + hDrawable_ = limitXCreatePixmap( GetXDisplay(), + pDisplay_->GetDrawable( m_nXScreen ), + nDX_, nDY_, + GetDepth() ); + bExternPixmap_ = false; + + if( nBitCount != pDisplay_->GetVisual( m_nXScreen ).GetDepth() ) { - ::Window aRoot; - int x, y; - unsigned int w = 0, h = 0, bw, d; - Display* pDisp = pDisplay_->GetDisplay(); - XGetGeometry( pDisp, pData->hDrawable, - &aRoot, &x, &y, &w, &h, &bw, &d ); - int nScreen = 0; - while( nScreen < ScreenCount( pDisp ) ) - { - if( RootWindow( pDisp, nScreen ) == aRoot ) - break; - nScreen++; - } - nDX_ = static_cast<tools::Long>(w); - nDY_ = static_cast<tools::Long>(h); - nDX = nDX_; - nDY = nDY_; - m_nXScreen = SalX11Screen( nScreen ); - hDrawable_ = pData->hDrawable; - bExternPixmap_ = true; + pColormap = new SalColormap( nBitCount ); + bDeleteColormap = true; } - else + + pGraphics_->SetLayout( SalLayoutFlags::NONE ); // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL() + + // tdf#127529 see SvpSalInstance::CreateVirtualDevice for the rare case of a non-null pPreExistingTarget + m_bOwnsSurface = true; + m_pSurface = cairo_xlib_surface_create(GetXDisplay(), hDrawable_, + pDisplay_->GetColormap(m_nXScreen).GetVisual().visual, + nDX_, nDY_); + + pGraphics_->Init(this, pColormap, bDeleteColormap); +} + +X11SalVirtualDevice::X11SalVirtualDevice(const SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, + DeviceFormat /*eFormat*/, const SystemGraphicsData& rData, + std::unique_ptr<X11SalGraphics> pNewGraphics) : + pGraphics_(std::move(pNewGraphics)), + m_nXScreen(0), + bGraphics_(false) +{ + SalColormap* pColormap = nullptr; + bool bDeleteColormap = false; + + sal_uInt16 nBitCount = rGraphics.GetBitCount(); + pDisplay_ = vcl_sal::getSalDisplay(GetGenericUnixSalData()); + nDepth_ = nBitCount; + + assert(rData.hDrawable != None); + + ::Window aRoot; + int x, y; + unsigned int w = 0, h = 0, bw, d; + Display* pDisp = pDisplay_->GetDisplay(); + XGetGeometry( pDisp, rData.hDrawable, + &aRoot, &x, &y, &w, &h, &bw, &d ); + int nScreen = 0; + while( nScreen < ScreenCount( pDisp ) ) { - nDX_ = nDX; - nDY_ = nDY; - m_nXScreen = static_cast<const X11SalGraphics&>(rGraphics).GetScreenNumber(); - hDrawable_ = limitXCreatePixmap( GetXDisplay(), - pDisplay_->GetDrawable( m_nXScreen ), - nDX_, nDY_, - GetDepth() ); - bExternPixmap_ = false; + if( RootWindow( pDisp, nScreen ) == aRoot ) + break; + nScreen++; } + nDX_ = static_cast<tools::Long>(w); + nDY_ = static_cast<tools::Long>(h); + nDX = nDX_; + nDY = nDY_; + m_nXScreen = SalX11Screen( nScreen ); + hDrawable_ = rData.hDrawable; + bExternPixmap_ = true; if( nBitCount != pDisplay_->GetVisual( m_nXScreen ).GetDepth() ) { @@ -140,7 +187,7 @@ X11SalVirtualDevice::X11SalVirtualDevice(const SalGraphics& rGraphics, tools::Lo pGraphics_->SetLayout( SalLayoutFlags::NONE ); // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL() // tdf#127529 see SvpSalInstance::CreateVirtualDevice for the rare case of a non-null pPreExistingTarget - cairo_surface_t* pPreExistingTarget = pData ? static_cast<cairo_surface_t*>(pData->pSurface) : nullptr; + cairo_surface_t* pPreExistingTarget = static_cast<cairo_surface_t*>(rData.pSurface); if (pPreExistingTarget) { m_bOwnsSurface = false; diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index 2550c134b356..24d923728cd5 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -368,16 +368,30 @@ void GtkYieldMutex::ThreadsLeave() release(true); } +std::unique_ptr<SalVirtualDevice> GtkInstance::CreateVirtualDevice( SalGraphics &rG, + tools::Long nDX, tools::Long nDY, + DeviceFormat /*eFormat*/ ) +{ + EnsureInit(); + SvpSalGraphics *pSvpSalGraphics = dynamic_cast<SvpSalGraphics*>(&rG); + assert(pSvpSalGraphics); + // tdf#127529 see SvpSalInstance::CreateVirtualDevice for the rare case of a non-null pPreExistingTarget + std::unique_ptr<SalVirtualDevice> xNew(new SvpSalVirtualDevice(pSvpSalGraphics->getSurface(), /*pPreExistingTarget*/nullptr)); + if (!xNew->SetSize(nDX, nDY)) + xNew.reset(); + return xNew; +} + std::unique_ptr<SalVirtualDevice> GtkInstance::CreateVirtualDevice( SalGraphics &rG, tools::Long &nDX, tools::Long &nDY, DeviceFormat /*eFormat*/, - const SystemGraphicsData* pGd ) + const SystemGraphicsData& rGd ) { EnsureInit(); SvpSalGraphics *pSvpSalGraphics = dynamic_cast<SvpSalGraphics*>(&rG); assert(pSvpSalGraphics); // tdf#127529 see SvpSalInstance::CreateVirtualDevice for the rare case of a non-null pPreExistingTarget - cairo_surface_t* pPreExistingTarget = pGd ? static_cast<cairo_surface_t*>(pGd->pSurface) : nullptr; + cairo_surface_t* pPreExistingTarget = static_cast<cairo_surface_t*>(rGd.pSurface); std::unique_ptr<SalVirtualDevice> xNew(new SvpSalVirtualDevice(pSvpSalGraphics->getSurface(), pPreExistingTarget)); if (!xNew->SetSize(nDX, nDY)) xNew.reset(); diff --git a/vcl/win/gdi/salvd.cxx b/vcl/win/gdi/salvd.cxx index 2f6d3456a748..7465d56570cb 100644 --- a/vcl/win/gdi/salvd.cxx +++ b/vcl/win/gdi/salvd.cxx @@ -71,53 +71,76 @@ HBITMAP WinSalVirtualDevice::ImplCreateVirDevBitmap(HDC hDC, tools::Long nDX, to return hBitmap; } +std::unique_ptr<SalVirtualDevice> WinSalInstance::CreateVirtualDevice( SalGraphics& rSGraphics, + tools::Long nDX, tools::Long nDY, + DeviceFormat /*eFormat*/ ) +{ + WinSalGraphics& rGraphics = static_cast<WinSalGraphics&>(rSGraphics); + + HDC hDC = CreateCompatibleDC( rGraphics.getHDC() ); + SAL_WARN_IF( !hDC, "vcl", "CreateCompatibleDC failed: " << WindowsErrorString( GetLastError() ) ); + + if (!hDC) + return nullptr; + + const sal_uInt16 nBitCount = 0; + // #124826# continue even if hBmp could not be created + // if we would return a failure in this case, the process + // would terminate which is not required + HBITMAP hBmp = WinSalVirtualDevice::ImplCreateVirDevBitmap(rGraphics.getHDC(), + nDX, nDY, nBitCount, + &o3tl::temporary<void*>(nullptr)); + + const SalData* pSalData = GetSalData(); + + WinSalVirtualDevice* pVDev = new WinSalVirtualDevice(hDC, hBmp, nBitCount, + /*bForeignDC*/false, nDX, nDY); + + WinSalGraphics* pVirGraphics = new WinSalGraphics(WinSalGraphics::VIRTUAL_DEVICE, + rGraphics.isScreen(), nullptr, pVDev); + + // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL() + pVirGraphics->SetLayout( SalLayoutFlags::NONE ); + pVirGraphics->setHDC(hDC); + + if ( pSalData->mhDitherPal && pVirGraphics->isScreen() ) + { + pVirGraphics->setPalette(pSalData->mhDitherPal); + RealizePalette( hDC ); + } + + pVDev->setGraphics(pVirGraphics); + + return std::unique_ptr<SalVirtualDevice>(pVDev); +} + std::unique_ptr<SalVirtualDevice> WinSalInstance::CreateVirtualDevice( SalGraphics& rSGraphics, tools::Long &nDX, tools::Long &nDY, DeviceFormat /*eFormat*/, - const SystemGraphicsData* pData ) + const SystemGraphicsData& rData ) { WinSalGraphics& rGraphics = static_cast<WinSalGraphics&>(rSGraphics); - HDC hDC = nullptr; - if( pData ) + HDC hDC = rData.hDC ? rData.hDC : GetDC(rData.hWnd); + if (hDC) { - hDC = (pData->hDC) ? pData->hDC : GetDC(pData->hWnd); - if (hDC) - { - nDX = GetDeviceCaps( hDC, HORZRES ); - nDY = GetDeviceCaps( hDC, VERTRES ); - } - else - { - nDX = 0; - nDY = 0; - } + nDX = GetDeviceCaps( hDC, HORZRES ); + nDY = GetDeviceCaps( hDC, VERTRES ); } else { - hDC = CreateCompatibleDC( rGraphics.getHDC() ); - SAL_WARN_IF( !hDC, "vcl", "CreateCompatibleDC failed: " << WindowsErrorString( GetLastError() ) ); + nDX = 0; + nDY = 0; } if (!hDC) return nullptr; - sal_uInt16 nBitCount = 0; - HBITMAP hBmp = nullptr; - if (!pData) - { - // #124826# continue even if hBmp could not be created - // if we would return a failure in this case, the process - // would terminate which is not required - hBmp = WinSalVirtualDevice::ImplCreateVirDevBitmap(rGraphics.getHDC(), - nDX, nDY, nBitCount, - &o3tl::temporary<void*>(nullptr)); - } - - const bool bForeignDC = pData != nullptr && pData->hDC != nullptr; + const sal_uInt16 nBitCount = 0; + const bool bForeignDC = rData.hDC != nullptr; const SalData* pSalData = GetSalData(); - WinSalVirtualDevice* pVDev = new WinSalVirtualDevice(hDC, hBmp, nBitCount, + WinSalVirtualDevice* pVDev = new WinSalVirtualDevice(hDC, /*hBmp*/nullptr, nBitCount, bForeignDC, nDX, nDY); WinSalGraphics* pVirGraphics = new WinSalGraphics(WinSalGraphics::VIRTUAL_DEVICE,