xref: /aoo42x/main/vcl/aqua/source/gdi/salgdiutils.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <boost/bind.hpp>
32 
33 #include "basebmp/scanlineformats.hxx"
34 #include "basebmp/color.hxx"
35 
36 #include "basegfx/range/b2drectangle.hxx"
37 #include "basegfx/range/b2irange.hxx"
38 #include "basegfx/vector/b2ivector.hxx"
39 #include "basegfx/polygon/b2dpolygon.hxx"
40 #include "basegfx/polygon/b2dpolygontools.hxx"
41 
42 #include "vcl/svapp.hxx"
43 
44 #include "aqua/salgdi.h"
45 #include "aqua/salframe.h"
46 #include "aqua/saldata.hxx"
47 
48 // ----------------------------------------------------------------------
49 
50 void AquaSalGraphics::SetWindowGraphics( AquaSalFrame* pFrame )
51 {
52     mpFrame     = pFrame;
53 
54     mbWindow    = true;
55     mbPrinter   = false;
56     mbVirDev    = false;
57 }
58 
59 void AquaSalGraphics::SetPrinterGraphics( CGContextRef xContext, long nDPIX, long nDPIY, double fScale )
60 {
61     mbWindow    = false;
62     mbPrinter   = true;
63     mbVirDev    = false;
64 
65     mrContext   = xContext;
66     mfFakeDPIScale = fScale;
67     mnRealDPIX  = nDPIX;
68     mnRealDPIY  = nDPIY;
69 
70     // a previously set clip path is now invalid
71     if( mxClipPath )
72     {
73         CGPathRelease( mxClipPath );
74         mxClipPath = NULL;
75     }
76 
77     if( mrContext )
78     {
79         CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace );
80         CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace );
81         CGContextSaveGState( mrContext );
82         SetState();
83     }
84 }
85 
86 void AquaSalGraphics::SetVirDevGraphics( CGLayerRef xLayer, CGContextRef xContext,
87 	int nBitmapDepth )
88 {
89     mbWindow    = false;
90     mbPrinter   = false;
91     mbVirDev    = true;
92 
93 	// set graphics properties
94 	mxLayer	= xLayer;
95 	mrContext = xContext;
96 	mnBitmapDepth = nBitmapDepth;
97 
98 	// return early if the virdev is being destroyed
99     if( !xContext )
100     	return;
101 
102 	// get new graphics properties
103     if( !mxLayer )
104     {
105 		mnWidth = CGBitmapContextGetWidth( mrContext );
106 		mnHeight = CGBitmapContextGetHeight( mrContext );
107     }
108     else
109     {
110 		const CGSize aSize = CGLayerGetSize( mxLayer );
111 		mnWidth = static_cast<int>(aSize.width);
112 		mnHeight = static_cast<int>(aSize.height);
113     }
114 
115 	// prepare graphics for drawing
116 	const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace;
117 	CGContextSetFillColorSpace( mrContext, aCGColorSpace );
118 	CGContextSetStrokeColorSpace( mrContext, aCGColorSpace );
119 
120 	// re-enable XorEmulation for the new context
121 	if( mpXorEmulation )
122 	{
123 		mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer );
124 		if( mpXorEmulation->IsEnabled() )
125 			mrContext = mpXorEmulation->GetMaskContext();
126 	}
127 
128 	// initialize stack of CGContext states
129 	CGContextSaveGState( mrContext );
130 	SetState();
131 }
132 
133 // ----------------------------------------------------------------------
134 
135 void AquaSalGraphics::InvalidateContext()
136 {
137     UnsetState();
138     mrContext = 0;
139 }
140 
141 // ----------------------------------------------------------------------
142 
143 void AquaSalGraphics::UnsetState()
144 {
145     if( mrContext )
146     {
147         CGContextRestoreGState( mrContext );
148         mrContext = 0;
149     }
150     if( mxClipPath )
151     {
152         CGPathRelease( mxClipPath );
153         mxClipPath = NULL;
154     }
155 }
156 
157 void AquaSalGraphics::SetState()
158 {
159     CGContextRestoreGState( mrContext );
160     CGContextSaveGState( mrContext );
161 
162 	// setup clipping
163 	if( mxClipPath )
164 	{
165 		CGContextBeginPath( mrContext );            // discard any existing path
166 		CGContextAddPath( mrContext, mxClipPath );  // set the current path to the clipping path
167 		CGContextClip( mrContext );                 // use it for clipping
168 	}
169 
170 	// set RGB colorspace and line and fill colors
171 	CGContextSetFillColor( mrContext, maFillColor.AsArray() );
172 	CGContextSetStrokeColor( mrContext, maLineColor.AsArray() );
173     CGContextSetShouldAntialias( mrContext, false );
174     if( mnXorMode == 2 )
175         CGContextSetBlendMode( mrContext, kCGBlendModeDifference );
176 }
177 
178 // ----------------------------------------------------------------------
179 
180 bool AquaSalGraphics::CheckContext()
181 {
182     if( mbWindow && mpFrame != NULL )
183     {
184         const unsigned int nWidth = mpFrame->maGeometry.nWidth;
185         const unsigned int nHeight = mpFrame->maGeometry.nHeight;
186 
187         CGContextRef rReleaseContext = 0;
188         CGLayerRef   rReleaseLayer = NULL;
189 
190 		// check if a new drawing context is needed (e.g. after a resize)
191 		if( (unsigned(mnWidth) != nWidth) || (unsigned(mnHeight) != nHeight) )
192 		{
193 			mnWidth = nWidth;
194 			mnHeight = nHeight;
195 			// prepare to release the corresponding resources
196 			rReleaseContext = mrContext;
197 			rReleaseLayer   = mxLayer;
198 			mrContext = NULL;
199 			mxLayer = NULL;
200 		}
201 
202         if( !mrContext )
203         {
204 	        const CGSize aLayerSize = {nWidth,nHeight};
205 	        NSGraphicsContext* pNSGContext = [NSGraphicsContext graphicsContextWithWindow: mpFrame->getWindow()];
206 	        CGContextRef xCGContext = reinterpret_cast<CGContextRef>([pNSGContext graphicsPort]);
207     	    mxLayer = CGLayerCreateWithContext( xCGContext, aLayerSize, NULL );
208 			if( mxLayer )
209 				mrContext = CGLayerGetContext( mxLayer );
210 
211             if( mrContext )
212             {
213                 // copy original layer to resized layer
214                 if( rReleaseLayer )
215                 	CGContextDrawLayerAtPoint( mrContext, CGPointZero, rReleaseLayer );
216 
217                 CGContextTranslateCTM( mrContext, 0, nHeight );
218                 CGContextScaleCTM( mrContext, 1.0, -1.0 );
219                 CGContextSetFillColorSpace( mrContext, GetSalData()->mxRGBSpace );
220                 CGContextSetStrokeColorSpace( mrContext, GetSalData()->mxRGBSpace );
221                 CGContextSaveGState( mrContext );
222                 SetState();
223 
224 				// re-enable XOR emulation for the new context
225 				if( mpXorEmulation )
226 					mpXorEmulation->SetTarget( mnWidth, mnHeight, mnBitmapDepth, mrContext, mxLayer );
227             }
228         }
229 
230 		if( rReleaseLayer )
231 			CGLayerRelease( rReleaseLayer );
232         else if( rReleaseContext )
233             CGContextRelease( rReleaseContext );
234     }
235 
236 	DBG_ASSERT( mrContext || mbPrinter, "<<<WARNING>>> AquaSalGraphics::CheckContext() FAILED!!!!\n" );
237 	return (mrContext != NULL);
238 }
239 
240 
241 void AquaSalGraphics::RefreshRect(float lX, float lY, float lWidth, float lHeight)
242 {
243     if( ! mbWindow ) // view only on Window graphics
244         return;
245 
246     if( mpFrame )
247     {
248         // update a little more around the designated rectangle
249         // this helps with antialiased rendering
250         const Rectangle aVclRect(Point(static_cast<long int>(lX-1),
251 					static_cast<long int>(lY-1) ),
252 				 Size( 	static_cast<long int>(lWidth+2),
253 					static_cast<long int>(lHeight+2) ) );
254         mpFrame->maInvalidRect.Union( aVclRect );
255     }
256 }
257 
258 CGPoint* AquaSalGraphics::makeCGptArray(sal_uLong nPoints, const SalPoint*  pPtAry)
259 {
260     CGPoint *CGpoints = new (CGPoint[nPoints]);
261     if ( CGpoints )
262       {
263         for(sal_uLong i=0;i<nPoints;i++)
264           {
265             CGpoints[i].x = (float)(pPtAry[i].mnX);
266             CGpoints[i].y = (float)(pPtAry[i].mnY);
267           }
268       }
269     return CGpoints;
270 }
271 
272 // -----------------------------------------------------------------------
273 
274 void AquaSalGraphics::UpdateWindow( NSRect& )
275 {
276 	if( !mpFrame )
277 		return;
278     NSGraphicsContext* pContext = [NSGraphicsContext currentContext];
279 	if( (mxLayer != NULL) && (pContext != NULL) )
280 	{
281         CGContextRef rCGContext = reinterpret_cast<CGContextRef>([pContext graphicsPort]);
282 
283         CGMutablePathRef rClip = mpFrame->getClipPath();
284         if( rClip )
285         {
286             CGContextSaveGState( rCGContext );
287             CGContextBeginPath( rCGContext );
288             CGContextAddPath( rCGContext, rClip );
289             CGContextClip( rCGContext );
290         }
291 
292 		ApplyXorContext();
293 		CGContextDrawLayerAtPoint( rCGContext, CGPointZero, mxLayer );
294         if( rClip ) // cleanup clipping
295             CGContextRestoreGState( rCGContext );
296 	}
297     else
298         DBG_ASSERT( mpFrame->mbInitShow, "UpdateWindow called on uneligible graphics" );
299 }
300 
301 // -----------------------------------------------------------------------
302 
303