1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salvd.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
37 #include "saldata.hxx"
40 #include "vcl/sysdata.hxx"
42 // -----------------------------------------------------------------------
44 SalVirtualDevice
* AquaSalInstance::CreateVirtualDevice( SalGraphics
* pGraphics
,
45 long nDX
, long nDY
, USHORT nBitCount
, const SystemGraphicsData
*pData
)
47 // #i92075# can be called first in a thread
48 SalData::ensureThreadAutoreleasePool();
50 return new AquaSalVirtualDevice( static_cast< AquaSalGraphics
* >( pGraphics
), nDX
, nDY
, nBitCount
, pData
);
53 // -----------------------------------------------------------------------
55 void AquaSalInstance::DestroyVirtualDevice( SalVirtualDevice
* pDevice
)
60 // =======================================================================
62 AquaSalVirtualDevice::AquaSalVirtualDevice( AquaSalGraphics
* pGraphic
, long nDX
, long nDY
, USHORT nBitCount
, const SystemGraphicsData
*pData
)
63 : mbGraphicsUsed( false )
64 , mxBitmapContext( NULL
)
68 if( pGraphic
&& pData
&& pData
->rCGContext
)
70 // Create virtual device based on existing SystemGraphicsData
71 // We ignore nDx and nDY, as the desired size comes from the SystemGraphicsData
72 mbForeignContext
= true; // the mxContext is from pData
73 mpGraphics
= new AquaSalGraphics( /*pGraphic*/ );
74 mpGraphics
->SetVirDevGraphics( mxLayer
, pData
->rCGContext
);
78 // create empty new virtual device
79 mbForeignContext
= false; // the mxContext is created within VCL
80 mpGraphics
= new AquaSalGraphics(); // never fails
81 mnBitmapDepth
= nBitCount
;
83 // inherit resolution from reference device
86 AquaSalFrame
* pFrame
= pGraphic
->getGraphicsFrame();
87 if( pFrame
&& AquaSalFrame::isAlive( pFrame
) )
89 mpGraphics
->setGraphicsFrame( pFrame
);
90 mpGraphics
->copyResolution( *pGraphic
);
97 // NOTE: if SetSize does not succeed, we just ignore the nDX and nDY
101 // -----------------------------------------------------------------------
103 AquaSalVirtualDevice::~AquaSalVirtualDevice()
107 mpGraphics
->SetVirDevGraphics( NULL
, NULL
);
114 // -----------------------------------------------------------------------
116 void AquaSalVirtualDevice::Destroy()
118 if( mbForeignContext
) {
119 // Do not delete mxContext that we have received from outside VCL
127 mpGraphics
->SetVirDevGraphics( NULL
, NULL
);
128 CGLayerRelease( mxLayer
);
132 if( mxBitmapContext
)
134 void* pRawData
= CGBitmapContextGetData( mxBitmapContext
);
135 rtl_freeMemory( pRawData
);
136 CGContextRelease( mxBitmapContext
);
137 mxBitmapContext
= NULL
;
141 // -----------------------------------------------------------------------
143 SalGraphics
* AquaSalVirtualDevice::GetGraphics()
145 if( mbGraphicsUsed
|| !mpGraphics
)
148 mbGraphicsUsed
= true;
152 // -----------------------------------------------------------------------
154 void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics
*pGraphics
)
156 mbGraphicsUsed
= false;
159 // -----------------------------------------------------------------------
161 BOOL
AquaSalVirtualDevice::SetSize( long nDX
, long nDY
)
163 if( mbForeignContext
)
165 // Do not delete/resize mxContext that we have received from outside VCL
171 const CGSize aSize
= CGLayerGetSize( mxLayer
);
172 if( (nDX
== aSize
.width
) && (nDY
== aSize
.height
) )
174 // Yay, we do not have to do anything :)
181 // create a Quartz layer matching to the intended virdev usage
182 CGContextRef xCGContext
= NULL
;
183 if( mnBitmapDepth
&& (mnBitmapDepth
< 16) )
185 mnBitmapDepth
= 8; // TODO: are 1bit vdevs worth it?
186 const CGColorSpaceRef aCGColorSpace
= GetSalData()->mxGraySpace
;
187 const CGBitmapInfo aCGBmpInfo
= kCGImageAlphaNone
;
188 const int nBytesPerRow
= (mnBitmapDepth
* nDX
+ 7) / 8;
190 void* pRawData
= rtl_allocateMemory( nBytesPerRow
* nDY
);
191 mxBitmapContext
= ::CGBitmapContextCreate( pRawData
, nDX
, nDY
,
192 mnBitmapDepth
, nBytesPerRow
, aCGColorSpace
, aCGBmpInfo
);
193 xCGContext
= mxBitmapContext
;
197 // default to a NSView target context
198 AquaSalFrame
* pSalFrame
= mpGraphics
->getGraphicsFrame();
199 if( !pSalFrame
&& !GetSalData()->maFrames
.empty() )
200 pSalFrame
= *GetSalData()->maFrames
.begin();
203 NSGraphicsContext
* pNSContext
= [NSGraphicsContext graphicsContextWithWindow
: pSalFrame
->getWindow()];
205 xCGContext
= reinterpret_cast<CGContextRef
>([pNSContext graphicsPort
]);
209 DBG_ASSERT( xCGContext
, "no context" );
211 const CGSize aNewSize
= { nDX
, nDY
};
212 mxLayer
= CGLayerCreateWithContext( xCGContext
, aNewSize
, NULL
);
214 if( mxLayer
&& mpGraphics
)
216 // get the matching Quartz context
217 CGContextRef xDrawContext
= CGLayerGetContext( mxLayer
);
218 mpGraphics
->SetVirDevGraphics( mxLayer
, xDrawContext
, mnBitmapDepth
);
221 return (mxLayer
!= NULL
);
224 // -----------------------------------------------------------------------
226 void AquaSalVirtualDevice::GetSize( long& rWidth
, long& rHeight
)
230 const CGSize aSize
= CGLayerGetSize( mxLayer
);
231 rWidth
= static_cast<long>(aSize
.width
);
232 rHeight
= static_cast<long>(aSize
.height
);