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