xref: /aoo41x/main/vcl/aqua/source/gdi/salgdiutils.cxx (revision 29f7de43)
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