xref: /trunk/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