xref: /AOO41X/main/vcl/aqua/source/gdi/salvd.cxx (revision bde8a4bd43e7fa360732f30ecf52c869f47a5d51)
19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
39f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
59f62ea84SAndrew Rist  * distributed with this work for additional information
69f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
79f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
139f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist  * software distributed under the License is distributed on an
159f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
179f62ea84SAndrew Rist  * specific language governing permissions and limitations
189f62ea84SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
209f62ea84SAndrew Rist  *************************************************************/
219f62ea84SAndrew Rist 
229f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "vcl/svapp.hxx"
28cdf0e10cSrcweir #include "vcl/sysdata.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include "aqua/salvd.h"
31cdf0e10cSrcweir #include "aqua/salinst.h"
32cdf0e10cSrcweir #include "aqua/salgdi.h"
33cdf0e10cSrcweir #include "aqua/saldata.hxx"
34cdf0e10cSrcweir #include "aqua/salframe.h"
35cdf0e10cSrcweir 
36cdf0e10cSrcweir // -----------------------------------------------------------------------
37cdf0e10cSrcweir 
CreateVirtualDevice(SalGraphics * pGraphics,long nDX,long nDY,sal_uInt16 nBitCount,const SystemGraphicsData * pData)38cdf0e10cSrcweir SalVirtualDevice* AquaSalInstance::CreateVirtualDevice( SalGraphics* pGraphics,
39cdf0e10cSrcweir 	long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData )
40cdf0e10cSrcweir {
41cdf0e10cSrcweir     // #i92075# can be called first in a thread
42cdf0e10cSrcweir     SalData::ensureThreadAutoreleasePool();
43cdf0e10cSrcweir 
44cdf0e10cSrcweir 	return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ), nDX, nDY, nBitCount, pData );
45cdf0e10cSrcweir }
46cdf0e10cSrcweir 
47cdf0e10cSrcweir // -----------------------------------------------------------------------
48cdf0e10cSrcweir 
DestroyVirtualDevice(SalVirtualDevice * pDevice)49cdf0e10cSrcweir void AquaSalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice )
50cdf0e10cSrcweir {
51cdf0e10cSrcweir 	delete pDevice;
52cdf0e10cSrcweir }
53cdf0e10cSrcweir 
54cdf0e10cSrcweir // =======================================================================
55cdf0e10cSrcweir 
AquaSalVirtualDevice(AquaSalGraphics * pGraphic,long nDX,long nDY,sal_uInt16 nBitCount,const SystemGraphicsData * pData)56cdf0e10cSrcweir AquaSalVirtualDevice::AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long nDX, long nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData )
57cdf0e10cSrcweir :	mbGraphicsUsed( false )
58cdf0e10cSrcweir ,	mxBitmapContext( NULL )
59cdf0e10cSrcweir ,	mnBitmapDepth( 0 )
60cdf0e10cSrcweir ,	mxLayer( NULL )
61cdf0e10cSrcweir {
62cdf0e10cSrcweir     if( pGraphic && pData && pData->rCGContext )
63cdf0e10cSrcweir 	{
64cdf0e10cSrcweir 	    // Create virtual device based on existing SystemGraphicsData
65cdf0e10cSrcweir         // We ignore nDx and nDY, as the desired size comes from the SystemGraphicsData
66cdf0e10cSrcweir         mbForeignContext = true;        // the mxContext is from pData
67cdf0e10cSrcweir 	    mpGraphics = new AquaSalGraphics( /*pGraphic*/ );
68cdf0e10cSrcweir 	    mpGraphics->SetVirDevGraphics( mxLayer, pData->rCGContext );
69cdf0e10cSrcweir 	}
70cdf0e10cSrcweir 	else
71cdf0e10cSrcweir 	{
72cdf0e10cSrcweir 	    // create empty new virtual device
73cdf0e10cSrcweir         mbForeignContext = false;           // the mxContext is created within VCL
74cdf0e10cSrcweir         mpGraphics = new AquaSalGraphics(); // never fails
75cdf0e10cSrcweir 		mnBitmapDepth = nBitCount;
76cdf0e10cSrcweir 
77cdf0e10cSrcweir         // inherit resolution from reference device
78cdf0e10cSrcweir         if( pGraphic )
79cdf0e10cSrcweir         {
80cdf0e10cSrcweir             AquaSalFrame* pFrame = pGraphic->getGraphicsFrame();
81cdf0e10cSrcweir             if( pFrame && AquaSalFrame::isAlive( pFrame ) )
82cdf0e10cSrcweir             {
83cdf0e10cSrcweir                 mpGraphics->setGraphicsFrame( pFrame );
84cdf0e10cSrcweir                 mpGraphics->copyResolution( *pGraphic );
85cdf0e10cSrcweir             }
86cdf0e10cSrcweir         }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir         if( nDX && nDY )
89cdf0e10cSrcweir             SetSize( nDX, nDY );
90cdf0e10cSrcweir 
91cdf0e10cSrcweir         // NOTE: if SetSize does not succeed, we just ignore the nDX and nDY
92cdf0e10cSrcweir 	}
93cdf0e10cSrcweir }
94cdf0e10cSrcweir 
95cdf0e10cSrcweir // -----------------------------------------------------------------------
96cdf0e10cSrcweir 
~AquaSalVirtualDevice()97cdf0e10cSrcweir AquaSalVirtualDevice::~AquaSalVirtualDevice()
98cdf0e10cSrcweir {
99cdf0e10cSrcweir 	if( mpGraphics )
100cdf0e10cSrcweir 	{
101cdf0e10cSrcweir 		mpGraphics->SetVirDevGraphics( NULL, NULL );
102cdf0e10cSrcweir 		delete mpGraphics;
103cdf0e10cSrcweir 		mpGraphics = 0;
104cdf0e10cSrcweir 	}
105cdf0e10cSrcweir 	Destroy();
106cdf0e10cSrcweir }
107cdf0e10cSrcweir 
108cdf0e10cSrcweir // -----------------------------------------------------------------------
109cdf0e10cSrcweir 
Destroy()110cdf0e10cSrcweir void AquaSalVirtualDevice::Destroy()
111cdf0e10cSrcweir {
112cdf0e10cSrcweir     if( mbForeignContext ) {
113cdf0e10cSrcweir         // Do not delete mxContext that we have received from outside VCL
114cdf0e10cSrcweir 		mxLayer = NULL;
115cdf0e10cSrcweir         return;
116cdf0e10cSrcweir     }
117cdf0e10cSrcweir 
118cdf0e10cSrcweir 	if( mxLayer )
119cdf0e10cSrcweir 	{
120cdf0e10cSrcweir 		if( mpGraphics )
121cdf0e10cSrcweir 			mpGraphics->SetVirDevGraphics( NULL, NULL );
122cdf0e10cSrcweir 		CGLayerRelease( mxLayer );
123cdf0e10cSrcweir 		mxLayer = NULL;
124cdf0e10cSrcweir 	}
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 	if( mxBitmapContext )
127cdf0e10cSrcweir 	{
128cdf0e10cSrcweir 		void* pRawData = CGBitmapContextGetData( mxBitmapContext );
129cdf0e10cSrcweir 		rtl_freeMemory( pRawData );
130cdf0e10cSrcweir 		CGContextRelease( mxBitmapContext );
131cdf0e10cSrcweir 		mxBitmapContext = NULL;
132cdf0e10cSrcweir 	}
133cdf0e10cSrcweir }
134cdf0e10cSrcweir 
135cdf0e10cSrcweir // -----------------------------------------------------------------------
136cdf0e10cSrcweir 
GetGraphics()137cdf0e10cSrcweir SalGraphics* AquaSalVirtualDevice::GetGraphics()
138cdf0e10cSrcweir {
139cdf0e10cSrcweir 	if( mbGraphicsUsed || !mpGraphics )
140cdf0e10cSrcweir 		return 0;
141cdf0e10cSrcweir 
142cdf0e10cSrcweir 	mbGraphicsUsed = true;
143cdf0e10cSrcweir 	return mpGraphics;
144cdf0e10cSrcweir }
145cdf0e10cSrcweir 
146cdf0e10cSrcweir // -----------------------------------------------------------------------
147cdf0e10cSrcweir 
ReleaseGraphics(SalGraphics *)148cdf0e10cSrcweir void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics* )
149cdf0e10cSrcweir {
150cdf0e10cSrcweir 	mbGraphicsUsed = false;
151cdf0e10cSrcweir }
152cdf0e10cSrcweir 
153cdf0e10cSrcweir // -----------------------------------------------------------------------
154cdf0e10cSrcweir 
SetSize(long nDX,long nDY)155cdf0e10cSrcweir sal_Bool AquaSalVirtualDevice::SetSize( long nDX, long nDY )
156cdf0e10cSrcweir {
157cdf0e10cSrcweir     if( mbForeignContext )
158cdf0e10cSrcweir     {
159cdf0e10cSrcweir         // Do not delete/resize mxContext that we have received from outside VCL
160cdf0e10cSrcweir         return true;
161cdf0e10cSrcweir     }
162cdf0e10cSrcweir 
163cdf0e10cSrcweir     if( mxLayer )
164cdf0e10cSrcweir     {
165cdf0e10cSrcweir     	const CGSize aSize = CGLayerGetSize( mxLayer );
166cdf0e10cSrcweir         if( (nDX == aSize.width) && (nDY == aSize.height) )
167cdf0e10cSrcweir 	    {
168cdf0e10cSrcweir 	        // Yay, we do not have to do anything :)
169cdf0e10cSrcweir 			return true;
170cdf0e10cSrcweir 	    }
171cdf0e10cSrcweir     }
172cdf0e10cSrcweir 
173cdf0e10cSrcweir     Destroy();
174cdf0e10cSrcweir 
175cdf0e10cSrcweir 	// create a Quartz layer matching to the intended virdev usage
176cdf0e10cSrcweir 	CGContextRef xCGContext = NULL;
177cdf0e10cSrcweir 	if( mnBitmapDepth && (mnBitmapDepth < 16) )
178cdf0e10cSrcweir 	{
179cdf0e10cSrcweir 		mnBitmapDepth = 8;  // TODO: are 1bit vdevs worth it?
180cdf0e10cSrcweir 		const CGColorSpaceRef aCGColorSpace = GetSalData()->mxGraySpace;
181cdf0e10cSrcweir 		const CGBitmapInfo aCGBmpInfo = kCGImageAlphaNone;
182cdf0e10cSrcweir 		const int nBytesPerRow = (mnBitmapDepth * nDX + 7) / 8;
183cdf0e10cSrcweir 
184cdf0e10cSrcweir 		void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
185cdf0e10cSrcweir 		mxBitmapContext = ::CGBitmapContextCreate( pRawData, nDX, nDY,
186cdf0e10cSrcweir 			mnBitmapDepth, nBytesPerRow, aCGColorSpace, aCGBmpInfo );
187cdf0e10cSrcweir 		xCGContext = mxBitmapContext;
188cdf0e10cSrcweir 	}
189cdf0e10cSrcweir 	else
190cdf0e10cSrcweir 	{
1912f2a22e7SHerbert Dürr         // default to a NSView target context
192cdf0e10cSrcweir         AquaSalFrame* pSalFrame = mpGraphics->getGraphicsFrame();
193e109b37cSHerbert Dürr         if( !pSalFrame || !AquaSalFrame::isAlive( pSalFrame ))
1942f2a22e7SHerbert Dürr         {
195e109b37cSHerbert Dürr             if( !GetSalData()->maFrames.empty() )
1962f2a22e7SHerbert Dürr             {
1972f2a22e7SHerbert Dürr                 // get the first matching frame
198cdf0e10cSrcweir                 pSalFrame = *GetSalData()->maFrames.begin();
1992f2a22e7SHerbert Dürr                 // update the frame reference
2002f2a22e7SHerbert Dürr                 mpGraphics->setGraphicsFrame( pSalFrame );
2012f2a22e7SHerbert Dürr             }
2022f2a22e7SHerbert Dürr         }
203cdf0e10cSrcweir         if( pSalFrame )
204cdf0e10cSrcweir         {
205cdf0e10cSrcweir             // #i91990#
206*bde8a4bdSHerbert Dürr             NSWindow* pNSWindow = pSalFrame->getNSWindow();
207*bde8a4bdSHerbert Dürr             if ( pNSWindow )
208cdf0e10cSrcweir             {
209*bde8a4bdSHerbert Dürr                 NSGraphicsContext* pNSContext = [NSGraphicsContext graphicsContextWithWindow: pNSWindow];
210cdf0e10cSrcweir                 if( pNSContext )
211cdf0e10cSrcweir                     xCGContext = reinterpret_cast<CGContextRef>([pNSContext graphicsPort]);
212cdf0e10cSrcweir             }
213cdf0e10cSrcweir             else
214cdf0e10cSrcweir             {
215cdf0e10cSrcweir                 // fall back to a bitmap context
216cdf0e10cSrcweir                 mnBitmapDepth = 32;
217cdf0e10cSrcweir                 const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace;
218cdf0e10cSrcweir                 const CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst;
219cdf0e10cSrcweir                 const int nBytesPerRow = (mnBitmapDepth * nDX) / 8;
220cdf0e10cSrcweir 
221cdf0e10cSrcweir                 void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
222cdf0e10cSrcweir                 mxBitmapContext = ::CGBitmapContextCreate( pRawData, nDX, nDY,
223cdf0e10cSrcweir                                                            8, nBytesPerRow, aCGColorSpace, aCGBmpInfo );
224cdf0e10cSrcweir                 xCGContext = mxBitmapContext;
225cdf0e10cSrcweir             }
226cdf0e10cSrcweir         }
227cdf0e10cSrcweir 	}
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 	DBG_ASSERT( xCGContext, "no context" );
230cdf0e10cSrcweir 
231cd426cceSHerbert Dürr 	const CGSize aNewSize = CGSizeMake( nDX, nDY);
232cdf0e10cSrcweir 	mxLayer = CGLayerCreateWithContext( xCGContext, aNewSize, NULL );
233cdf0e10cSrcweir 
234cdf0e10cSrcweir 	if( mxLayer && mpGraphics )
235cdf0e10cSrcweir 	{
236cdf0e10cSrcweir 		// get the matching Quartz context
237cdf0e10cSrcweir 		CGContextRef xDrawContext = CGLayerGetContext( mxLayer );
238cdf0e10cSrcweir 		mpGraphics->SetVirDevGraphics( mxLayer, xDrawContext, mnBitmapDepth );
239cdf0e10cSrcweir 	}
240cdf0e10cSrcweir 
241cdf0e10cSrcweir 	return (mxLayer != NULL);
242cdf0e10cSrcweir }
243cdf0e10cSrcweir 
244cdf0e10cSrcweir // -----------------------------------------------------------------------
245cdf0e10cSrcweir 
GetSize(long & rWidth,long & rHeight)246cdf0e10cSrcweir void AquaSalVirtualDevice::GetSize( long& rWidth, long& rHeight )
247cdf0e10cSrcweir {
248cdf0e10cSrcweir 	if( mxLayer )
249cdf0e10cSrcweir 	{
250cdf0e10cSrcweir     	const CGSize aSize = CGLayerGetSize( mxLayer );
251cdf0e10cSrcweir 		rWidth = static_cast<long>(aSize.width);
252cdf0e10cSrcweir 		rHeight = static_cast<long>(aSize.height);
253cdf0e10cSrcweir 	}
254cdf0e10cSrcweir 	else
255cdf0e10cSrcweir 	{
256cdf0e10cSrcweir 		rWidth = 0;
257cdf0e10cSrcweir 		rHeight = 0;
258cdf0e10cSrcweir 	}
259cdf0e10cSrcweir }
260