update emoji autocorrect entries from po-files
[LibreOffice.git] / vcl / quartz / salvd.cxx
blobae25748dfa12fbda9ab8e14c9450e24e6ec40b3f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include "vcl/svapp.hxx"
21 #include "vcl/sysdata.hxx"
23 #include "quartz/salvd.h"
24 #ifdef MACOSX
25 #include "osx/salinst.h"
26 #include "osx/saldata.hxx"
27 #include "osx/salframe.h"
28 #else
29 #include "headless/svpframe.hxx"
30 #include "headless/svpgdi.hxx"
31 #include "headless/svpinst.hxx"
32 #include "headless/svpvd.hxx"
33 #endif
34 #include "quartz/salgdi.h"
35 #include "quartz/utils.h"
37 SalVirtualDevice* AquaSalInstance::CreateVirtualDevice( SalGraphics* pGraphics,
38 long &nDX, long &nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData )
40 // #i92075# can be called first in a thread
41 SalData::ensureThreadAutoreleasePool();
43 #ifdef IOS
44 if( pData )
45 return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ), nDX, nDY, nBitCount, pData );
46 else
48 AquaSalVirtualDevice* pNew = new AquaSalVirtualDevice( NULL, nDX, nDY, nBitCount, NULL );
49 pNew->SetSize( nDX, nDY );
50 return pNew;
52 #else
53 return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ), nDX, nDY, nBitCount, pData );
54 #endif
57 AquaSalVirtualDevice::AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long &nDX, long &nDY, sal_uInt16 nBitCount, const SystemGraphicsData *pData )
58 : mbGraphicsUsed( false )
59 , mxBitmapContext( NULL )
60 , mnBitmapDepth( 0 )
61 , mxLayer( NULL )
63 SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::AquaSalVirtualDevice() this=" << this << " size=(" << nDX << "x" << nDY << ") bitcount=" << nBitCount << " pData=" << pData << " context=" << (pData ? pData->rCGContext : 0) );
64 if( pGraphic && pData && pData->rCGContext )
66 // Create virtual device based on existing SystemGraphicsData
67 // We ignore nDx and nDY, as the desired size comes from the SystemGraphicsData.
68 mbForeignContext = true; // the mxContext is from pData (what "mxContext"? there is no such field anywhere in vcl;)
69 mpGraphics = new AquaSalGraphics( /*pGraphic*/ );
70 if (nDX == 0)
71 nDX = 1;
72 if (nDY == 0)
73 nDY = 1;
74 mxLayer = CGLayerCreateWithContext( pData->rCGContext, CGSizeMake( nDX, nDY), NULL );
75 // Interrogate the context as to its real size
76 if (mxLayer)
78 const CGSize aSize = CGLayerGetSize( mxLayer );
79 nDX = static_cast<long>(aSize.width);
80 nDY = static_cast<long>(aSize.height);
82 else
84 nDX = 0;
85 nDY = 0;
87 CG_TRACE( "CGLayerCreateWithContext(" << pData->rCGContext << "," << CGSizeMake( nDX, nDY) << ",NULL) = " << mxLayer );
88 mpGraphics->SetVirDevGraphics( mxLayer, pData->rCGContext );
90 else
92 // create empty new virtual device
93 mbForeignContext = false; // the mxContext is created within VCL
94 mpGraphics = new AquaSalGraphics(); // never fails
95 mnBitmapDepth = nBitCount;
96 #ifdef MACOSX
97 // inherit resolution from reference device
98 if( pGraphic )
100 AquaSalFrame* pFrame = pGraphic->getGraphicsFrame();
101 if( pFrame && AquaSalFrame::isAlive( pFrame ) )
103 mpGraphics->setGraphicsFrame( pFrame );
104 mpGraphics->copyResolution( *pGraphic );
107 #endif
108 if( nDX && nDY )
109 SetSize( nDX, nDY );
111 // NOTE: if SetSize does not succeed, we just ignore the nDX and nDY
115 AquaSalVirtualDevice::~AquaSalVirtualDevice()
117 SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::~AquaSalVirtualDevice() this=" << this );
118 if( mpGraphics )
120 mpGraphics->SetVirDevGraphics( NULL, NULL );
121 delete mpGraphics;
122 mpGraphics = 0;
124 Destroy();
127 void AquaSalVirtualDevice::Destroy()
129 SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::Destroy() this=" << this << " mbForeignContext=" << mbForeignContext );
131 if( mbForeignContext ) {
132 // Do not delete mxContext that we have received from outside VCL
133 mxLayer = NULL;
134 return;
137 if( mxLayer )
139 if( mpGraphics )
140 mpGraphics->SetVirDevGraphics( NULL, NULL );
141 CG_TRACE( "CGLayerRelease(" << mxLayer << ")" );
142 CGLayerRelease( mxLayer );
143 mxLayer = NULL;
146 if( mxBitmapContext )
148 void* pRawData = CGBitmapContextGetData( mxBitmapContext );
149 rtl_freeMemory( pRawData );
150 CG_TRACE( "CGContextRelease(" << mxBitmapContext << ")" );
151 CGContextRelease( mxBitmapContext );
152 mxBitmapContext = NULL;
156 SalGraphics* AquaSalVirtualDevice::AcquireGraphics()
158 if( mbGraphicsUsed || !mpGraphics )
159 return 0;
161 mbGraphicsUsed = true;
162 return mpGraphics;
165 void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics* )
167 mbGraphicsUsed = false;
170 bool AquaSalVirtualDevice::SetSize( long nDX, long nDY )
172 SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::SetSize() this=" << this << " (" << nDX << "x" << nDY << ") mbForeignContext=" << mbForeignContext );
174 if( mbForeignContext )
176 // Do not delete/resize mxContext that we have received from outside VCL
177 return true;
180 if( mxLayer )
182 const CGSize aSize = CGLayerGetSize( mxLayer );
183 CG_TRACE( "CGlayerGetSize(" << mxLayer << ") = " << aSize );
184 if( (nDX == aSize.width) && (nDY == aSize.height) )
186 // Yay, we do not have to do anything :)
187 return true;
191 Destroy();
193 // create a Quartz layer matching to the intended virdev usage
194 CGContextRef xCGContext = NULL;
195 if( mnBitmapDepth && (mnBitmapDepth < 16) )
197 mnBitmapDepth = 8; // TODO: are 1bit vdevs worth it?
198 const int nBytesPerRow = (mnBitmapDepth * nDX + 7) / 8;
200 void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
201 #ifdef DBG_UTIL
202 for (ssize_t i = 0; i < nBytesPerRow * nDY; i++)
203 static_cast<sal_uInt8*>(pRawData)[i] = (i & 0xFF);
204 #endif
205 mxBitmapContext = CGBitmapContextCreate( pRawData, nDX, nDY,
206 mnBitmapDepth, nBytesPerRow, GetSalData()->mxGraySpace, kCGImageAlphaNone );
207 CG_TRACE( "CGBitmapContextCreate(" << nDX << "x" << nDY << "x" << mnBitmapDepth << ") = " << mxBitmapContext );
208 xCGContext = mxBitmapContext;
210 else
212 #ifdef MACOSX
213 // default to a NSView target context
214 AquaSalFrame* pSalFrame = mpGraphics->getGraphicsFrame();
215 if( !pSalFrame || !AquaSalFrame::isAlive( pSalFrame ))
217 if( !GetSalData()->maFrames.empty() )
219 // get the first matching frame
220 pSalFrame = *GetSalData()->maFrames.begin();
222 else
224 // ensure we don't reuse a dead AquaSalFrame on the very
225 // unlikely case of no other frame to use
226 pSalFrame = NULL;
228 // update the frame reference
229 mpGraphics->setGraphicsFrame( pSalFrame );
231 if( pSalFrame )
233 // #i91990#
234 NSWindow* pNSWindow = pSalFrame->getNSWindow();
235 if ( pNSWindow )
237 NSGraphicsContext* pNSContext = [NSGraphicsContext graphicsContextWithWindow: pNSWindow];
238 if( pNSContext )
239 xCGContext = static_cast<CGContextRef>([pNSContext graphicsPort]);
241 else
243 // fall back to a bitmap context
244 mnBitmapDepth = 32;
245 const int nBytesPerRow = (mnBitmapDepth * nDX) / 8;
247 void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
248 #ifdef DBG_UTIL
249 for (ssize_t i = 0; i < nBytesPerRow * nDY; i++)
250 static_cast<sal_uInt8*>(pRawData)[i] = (i & 0xFF);
251 #endif
252 mxBitmapContext = CGBitmapContextCreate( pRawData, nDX, nDY,
253 8, nBytesPerRow, GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst );
254 CG_TRACE( "CGBitmapContextCreate(" << nDX << "x" << nDY << "x32) = " << mxBitmapContext );
255 xCGContext = mxBitmapContext;
258 #else
259 mnBitmapDepth = 32;
260 const int nBytesPerRow = (mnBitmapDepth * nDX) / 8;
262 void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
263 #ifdef DBG_UTIL
264 for (ssize_t i = 0; i < nBytesPerRow * nDY; i++)
265 ((sal_uInt8*)pRawData)[i] = (i & 0xFF);
266 #endif
267 mxBitmapContext = CGBitmapContextCreate( pRawData, nDX, nDY,
268 8, nBytesPerRow, GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst );
269 CG_TRACE( "CGBitmapContextCreate(" << nDX << "x" << nDY << "x32) = " << mxBitmapContext );
270 xCGContext = mxBitmapContext;
271 #endif
274 SAL_WARN_IF( !xCGContext, "vcl.quartz", "No context" );
276 const CGSize aNewSize = { static_cast<CGFloat>(nDX), static_cast<CGFloat>(nDY) };
277 mxLayer = CGLayerCreateWithContext( xCGContext, aNewSize, NULL );
278 CG_TRACE( "CGLayerCreateWithContext(" << xCGContext << "," << aNewSize << ",NULL) = " << mxLayer );
280 if( mxLayer && mpGraphics )
282 // get the matching Quartz context
283 CGContextRef xDrawContext = CGLayerGetContext( mxLayer );
284 CG_TRACE( "CGLayerGetContext(" << mxLayer << ") = " << xDrawContext );
285 mpGraphics->SetVirDevGraphics( mxLayer, xDrawContext, mnBitmapDepth );
288 return (mxLayer != NULL);
291 long AquaSalVirtualDevice::GetWidth() const
293 const CGSize aSize = CGLayerGetSize( mxLayer );
294 return aSize.width;
297 long AquaSalVirtualDevice::GetHeight() const
299 const CGSize aSize = CGLayerGetSize( mxLayer );
300 return aSize.height;
303 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */