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
109f62ea84SAndrew Rist *
119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist *
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.
199f62ea84SAndrew Rist *
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 <boost/bind.hpp>
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include "basebmp/scanlineformats.hxx"
30cdf0e10cSrcweir #include "basebmp/color.hxx"
31cdf0e10cSrcweir
32cdf0e10cSrcweir #include "basegfx/range/b2drectangle.hxx"
33cdf0e10cSrcweir #include "basegfx/range/b2irange.hxx"
34cdf0e10cSrcweir #include "basegfx/vector/b2ivector.hxx"
35cdf0e10cSrcweir #include "basegfx/polygon/b2dpolygon.hxx"
36cdf0e10cSrcweir #include "basegfx/polygon/b2dpolygontools.hxx"
37cdf0e10cSrcweir
38cdf0e10cSrcweir #include "vcl/svapp.hxx"
39cdf0e10cSrcweir
40cdf0e10cSrcweir #include "aqua/salgdi.h"
41cdf0e10cSrcweir #include "aqua/salframe.h"
42cdf0e10cSrcweir #include "aqua/saldata.hxx"
43cdf0e10cSrcweir
44cdf0e10cSrcweir // ----------------------------------------------------------------------
45cdf0e10cSrcweir
SetWindowGraphics(AquaSalFrame * pFrame)46cdf0e10cSrcweir void AquaSalGraphics::SetWindowGraphics( AquaSalFrame* pFrame )
47cdf0e10cSrcweir {
48cdf0e10cSrcweir mpFrame = pFrame;
49cdf0e10cSrcweir
50cdf0e10cSrcweir mbWindow = true;
51cdf0e10cSrcweir mbPrinter = false;
52cdf0e10cSrcweir mbVirDev = false;
53cdf0e10cSrcweir }
54cdf0e10cSrcweir
SetPrinterGraphics(CGContextRef xContext,long nDPIX,long nDPIY,double fScale)55cdf0e10cSrcweir void AquaSalGraphics::SetPrinterGraphics( CGContextRef xContext, long nDPIX, long nDPIY, double fScale )
56cdf0e10cSrcweir {
57cdf0e10cSrcweir mbWindow = false;
58cdf0e10cSrcweir mbPrinter = true;
59cdf0e10cSrcweir mbVirDev = false;
60cdf0e10cSrcweir
61cdf0e10cSrcweir mrContext = xContext;
62cdf0e10cSrcweir mfFakeDPIScale = fScale;
63cdf0e10cSrcweir mnRealDPIX = nDPIX;
64cdf0e10cSrcweir mnRealDPIY = nDPIY;
65cdf0e10cSrcweir
66cdf0e10cSrcweir // a previously set clip path is now invalid
67cdf0e10cSrcweir if( mxClipPath )
68cdf0e10cSrcweir {
69cdf0e10cSrcweir CGPathRelease( mxClipPath );
70cdf0e10cSrcweir mxClipPath = NULL;
71cdf0e10cSrcweir }
72cdf0e10cSrcweir
73cdf0e10cSrcweir if( mrContext )
74cdf0e10cSrcweir {
75cdf0e10cSrcweir CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace );
76cdf0e10cSrcweir CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace );
77cdf0e10cSrcweir CGContextSaveGState( mrContext );
78cdf0e10cSrcweir SetState();
79cdf0e10cSrcweir }
80cdf0e10cSrcweir }
81cdf0e10cSrcweir
SetVirDevGraphics(CGLayerRef xLayer,CGContextRef xContext,int nBitmapDepth)82cdf0e10cSrcweir void AquaSalGraphics::SetVirDevGraphics( CGLayerRef xLayer, CGContextRef xContext,
83cdf0e10cSrcweir int nBitmapDepth )
84cdf0e10cSrcweir {
85cdf0e10cSrcweir mbWindow = false;
86cdf0e10cSrcweir mbPrinter = false;
87cdf0e10cSrcweir mbVirDev = true;
88cdf0e10cSrcweir
89cdf0e10cSrcweir // set graphics properties
90cdf0e10cSrcweir mxLayer = xLayer;
91cdf0e10cSrcweir mrContext = xContext;
92cdf0e10cSrcweir mnBitmapDepth = nBitmapDepth;
93cdf0e10cSrcweir
94cdf0e10cSrcweir // return early if the virdev is being destroyed
95cdf0e10cSrcweir if( !xContext )
96cdf0e10cSrcweir return;
97cdf0e10cSrcweir
98cdf0e10cSrcweir // get new graphics properties
99cdf0e10cSrcweir if( !mxLayer )
100cdf0e10cSrcweir {
101cdf0e10cSrcweir mnWidth = CGBitmapContextGetWidth( mrContext );
102cdf0e10cSrcweir mnHeight = CGBitmapContextGetHeight( mrContext );
103cdf0e10cSrcweir }
104cdf0e10cSrcweir else
105cdf0e10cSrcweir {
106cdf0e10cSrcweir const CGSize aSize = CGLayerGetSize( mxLayer );
107cdf0e10cSrcweir mnWidth = static_cast<int>(aSize.width);
108cdf0e10cSrcweir mnHeight = static_cast<int>(aSize.height);
109cdf0e10cSrcweir }
110cdf0e10cSrcweir
111cdf0e10cSrcweir // prepare graphics for drawing
112cdf0e10cSrcweir const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace;
113cdf0e10cSrcweir CGContextSetFillColorSpace( mrContext, aCGColorSpace );
114cdf0e10cSrcweir CGContextSetStrokeColorSpace( mrContext, aCGColorSpace );
115cdf0e10cSrcweir
116cdf0e10cSrcweir // re-enable XorEmulation for the new context
117cdf0e10cSrcweir if( mpXorEmulation )
118cdf0e10cSrcweir {
119cdf0e10cSrcweir mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer );
120cdf0e10cSrcweir if( mpXorEmulation->IsEnabled() )
121cdf0e10cSrcweir mrContext = mpXorEmulation->GetMaskContext();
122cdf0e10cSrcweir }
123cdf0e10cSrcweir
124cdf0e10cSrcweir // initialize stack of CGContext states
125cdf0e10cSrcweir CGContextSaveGState( mrContext );
126cdf0e10cSrcweir SetState();
127cdf0e10cSrcweir }
128cdf0e10cSrcweir
129cdf0e10cSrcweir // ----------------------------------------------------------------------
130cdf0e10cSrcweir
InvalidateContext()131cdf0e10cSrcweir void AquaSalGraphics::InvalidateContext()
132cdf0e10cSrcweir {
133cdf0e10cSrcweir UnsetState();
134cdf0e10cSrcweir mrContext = 0;
135cdf0e10cSrcweir }
136cdf0e10cSrcweir
137cdf0e10cSrcweir // ----------------------------------------------------------------------
138cdf0e10cSrcweir
UnsetState()139cdf0e10cSrcweir void AquaSalGraphics::UnsetState()
140cdf0e10cSrcweir {
141cdf0e10cSrcweir if( mrContext )
142cdf0e10cSrcweir {
143cdf0e10cSrcweir CGContextRestoreGState( mrContext );
144cdf0e10cSrcweir mrContext = 0;
145cdf0e10cSrcweir }
146cdf0e10cSrcweir if( mxClipPath )
147cdf0e10cSrcweir {
148cdf0e10cSrcweir CGPathRelease( mxClipPath );
149cdf0e10cSrcweir mxClipPath = NULL;
150cdf0e10cSrcweir }
151cdf0e10cSrcweir }
152cdf0e10cSrcweir
SetState()153cdf0e10cSrcweir void AquaSalGraphics::SetState()
154cdf0e10cSrcweir {
155cdf0e10cSrcweir CGContextRestoreGState( mrContext );
156cdf0e10cSrcweir CGContextSaveGState( mrContext );
157cdf0e10cSrcweir
158cdf0e10cSrcweir // setup clipping
159cdf0e10cSrcweir if( mxClipPath )
160cdf0e10cSrcweir {
161cdf0e10cSrcweir CGContextBeginPath( mrContext ); // discard any existing path
162cdf0e10cSrcweir CGContextAddPath( mrContext, mxClipPath ); // set the current path to the clipping path
163cdf0e10cSrcweir CGContextClip( mrContext ); // use it for clipping
164cdf0e10cSrcweir }
165cdf0e10cSrcweir
166cdf0e10cSrcweir // set RGB colorspace and line and fill colors
167cdf0e10cSrcweir CGContextSetFillColor( mrContext, maFillColor.AsArray() );
168cdf0e10cSrcweir CGContextSetStrokeColor( mrContext, maLineColor.AsArray() );
169cdf0e10cSrcweir CGContextSetShouldAntialias( mrContext, false );
170cdf0e10cSrcweir if( mnXorMode == 2 )
171cdf0e10cSrcweir CGContextSetBlendMode( mrContext, kCGBlendModeDifference );
172cdf0e10cSrcweir }
173cdf0e10cSrcweir
174cdf0e10cSrcweir // ----------------------------------------------------------------------
175cdf0e10cSrcweir
CheckContext()176cdf0e10cSrcweir bool AquaSalGraphics::CheckContext()
177cdf0e10cSrcweir {
1782dae3561SHerbert Dürr if( mbWindow && mpFrame && mpFrame->getNSWindow() )
179cdf0e10cSrcweir {
180cdf0e10cSrcweir const unsigned int nWidth = mpFrame->maGeometry.nWidth;
181cdf0e10cSrcweir const unsigned int nHeight = mpFrame->maGeometry.nHeight;
182cdf0e10cSrcweir
183cdf0e10cSrcweir CGContextRef rReleaseContext = 0;
184cdf0e10cSrcweir CGLayerRef rReleaseLayer = NULL;
185cdf0e10cSrcweir
186cdf0e10cSrcweir // check if a new drawing context is needed (e.g. after a resize)
187cdf0e10cSrcweir if( (unsigned(mnWidth) != nWidth) || (unsigned(mnHeight) != nHeight) )
188cdf0e10cSrcweir {
189cdf0e10cSrcweir mnWidth = nWidth;
190cdf0e10cSrcweir mnHeight = nHeight;
191cdf0e10cSrcweir // prepare to release the corresponding resources
192cdf0e10cSrcweir rReleaseContext = mrContext;
193cdf0e10cSrcweir rReleaseLayer = mxLayer;
194cdf0e10cSrcweir mrContext = NULL;
195cdf0e10cSrcweir mxLayer = NULL;
196cdf0e10cSrcweir }
197cdf0e10cSrcweir
198cdf0e10cSrcweir if( !mrContext )
199cdf0e10cSrcweir {
200cd426cceSHerbert Dürr const CGSize aLayerSize = CGSizeMake( nWidth, nHeight);
201bde8a4bdSHerbert Dürr NSGraphicsContext* pNSGContext = [NSGraphicsContext graphicsContextWithWindow: mpFrame->getNSWindow()];
202cdf0e10cSrcweir CGContextRef xCGContext = reinterpret_cast<CGContextRef>([pNSGContext graphicsPort]);
203cdf0e10cSrcweir mxLayer = CGLayerCreateWithContext( xCGContext, aLayerSize, NULL );
204cdf0e10cSrcweir if( mxLayer )
205cdf0e10cSrcweir mrContext = CGLayerGetContext( mxLayer );
206cdf0e10cSrcweir
207cdf0e10cSrcweir if( mrContext )
208cdf0e10cSrcweir {
209cdf0e10cSrcweir // copy original layer to resized layer
210cdf0e10cSrcweir if( rReleaseLayer )
211cdf0e10cSrcweir CGContextDrawLayerAtPoint( mrContext, CGPointZero, rReleaseLayer );
212cdf0e10cSrcweir
213cdf0e10cSrcweir CGContextTranslateCTM( mrContext, 0, nHeight );
214cdf0e10cSrcweir CGContextScaleCTM( mrContext, 1.0, -1.0 );
215cdf0e10cSrcweir CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace );
216cdf0e10cSrcweir CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace );
217cdf0e10cSrcweir CGContextSaveGState( mrContext );
218cdf0e10cSrcweir SetState();
219cdf0e10cSrcweir
220cdf0e10cSrcweir // re-enable XOR emulation for the new context
221cdf0e10cSrcweir if( mpXorEmulation )
222cdf0e10cSrcweir mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer );
223cdf0e10cSrcweir }
224cdf0e10cSrcweir }
225cdf0e10cSrcweir
226cdf0e10cSrcweir if( rReleaseLayer )
227cdf0e10cSrcweir CGLayerRelease( rReleaseLayer );
228cdf0e10cSrcweir else if( rReleaseContext )
229cdf0e10cSrcweir CGContextRelease( rReleaseContext );
230cdf0e10cSrcweir }
231cdf0e10cSrcweir
232cdf0e10cSrcweir DBG_ASSERT( mrContext || mbPrinter, "<<<WARNING>>> AquaSalGraphics::CheckContext() FAILED!!!!\n" );
233cdf0e10cSrcweir return (mrContext != NULL);
234cdf0e10cSrcweir }
235cdf0e10cSrcweir
236cdf0e10cSrcweir
RefreshRect(float lX,float lY,float lWidth,float lHeight)237cdf0e10cSrcweir void AquaSalGraphics::RefreshRect(float lX, float lY, float lWidth, float lHeight)
238cdf0e10cSrcweir {
239cdf0e10cSrcweir if( ! mbWindow ) // view only on Window graphics
240cdf0e10cSrcweir return;
241cdf0e10cSrcweir
242cdf0e10cSrcweir if( mpFrame )
243cdf0e10cSrcweir {
244cdf0e10cSrcweir // update a little more around the designated rectangle
245cdf0e10cSrcweir // this helps with antialiased rendering
246*29f7de43SHerbert Dürr // Rounding down x and width can accumulate a rounding error of up to 2
247*29f7de43SHerbert Dürr // The decrementing of x, the rounding error and the antialiasing border
248*29f7de43SHerbert Dürr // require that the width and the height need to be increased by four
249cdf0e10cSrcweir const Rectangle aVclRect(Point(static_cast<long int>(lX-1),
250cdf0e10cSrcweir static_cast<long int>(lY-1) ),
251*29f7de43SHerbert Dürr Size( static_cast<long int>(lWidth+4),
252*29f7de43SHerbert Dürr static_cast<long int>(lHeight+4) ) );
253cdf0e10cSrcweir mpFrame->maInvalidRect.Union( aVclRect );
254cdf0e10cSrcweir }
255cdf0e10cSrcweir }
256cdf0e10cSrcweir
makeCGptArray(sal_uLong nPoints,const SalPoint * pPtAry)257cdf0e10cSrcweir CGPoint* AquaSalGraphics::makeCGptArray(sal_uLong nPoints, const SalPoint* pPtAry)
258cdf0e10cSrcweir {
259025194d6SHerbert Dürr CGPoint *CGpoints = new CGPoint[ nPoints];
260cdf0e10cSrcweir if ( CGpoints )
261cdf0e10cSrcweir {
262cdf0e10cSrcweir for(sal_uLong i=0;i<nPoints;i++)
263cdf0e10cSrcweir {
264cdf0e10cSrcweir CGpoints[i].x = (float)(pPtAry[i].mnX);
265cdf0e10cSrcweir CGpoints[i].y = (float)(pPtAry[i].mnY);
266cdf0e10cSrcweir }
267cdf0e10cSrcweir }
268cdf0e10cSrcweir return CGpoints;
269cdf0e10cSrcweir }
270cdf0e10cSrcweir
271cdf0e10cSrcweir // -----------------------------------------------------------------------
272cdf0e10cSrcweir
UpdateWindow(NSRect &)273cdf0e10cSrcweir void AquaSalGraphics::UpdateWindow( NSRect& )
274cdf0e10cSrcweir {
275cdf0e10cSrcweir if( !mpFrame )
276cdf0e10cSrcweir return;
277cdf0e10cSrcweir NSGraphicsContext* pContext = [NSGraphicsContext currentContext];
278cdf0e10cSrcweir if( (mxLayer != NULL) && (pContext != NULL) )
279cdf0e10cSrcweir {
280cdf0e10cSrcweir CGContextRef rCGContext = reinterpret_cast<CGContextRef>([pContext graphicsPort]);
281cdf0e10cSrcweir
282cdf0e10cSrcweir CGMutablePathRef rClip = mpFrame->getClipPath();
283cdf0e10cSrcweir if( rClip )
284cdf0e10cSrcweir {
285cdf0e10cSrcweir CGContextSaveGState( rCGContext );
286cdf0e10cSrcweir CGContextBeginPath( rCGContext );
287cdf0e10cSrcweir CGContextAddPath( rCGContext, rClip );
288cdf0e10cSrcweir CGContextClip( rCGContext );
289cdf0e10cSrcweir }
290cdf0e10cSrcweir
291cdf0e10cSrcweir ApplyXorContext();
292cdf0e10cSrcweir CGContextDrawLayerAtPoint( rCGContext, CGPointZero, mxLayer );
293cdf0e10cSrcweir if( rClip ) // cleanup clipping
294cdf0e10cSrcweir CGContextRestoreGState( rCGContext );
295cdf0e10cSrcweir }
296cdf0e10cSrcweir else
297cdf0e10cSrcweir DBG_ASSERT( mpFrame->mbInitShow, "UpdateWindow called on uneligible graphics" );
298cdf0e10cSrcweir }
299cdf0e10cSrcweir
300cdf0e10cSrcweir // -----------------------------------------------------------------------
301cdf0e10cSrcweir
302