xref: /trunk/main/vcl/aqua/source/gdi/salgdiutils.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
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
10cdf0e10cSrcweir  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
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*e2c1660dSHerbert Dürr         // Rounding down x and width can accumulate a rounding error of up to 2
247*e2c1660dSHerbert Dürr         // The decrementing of x, the rounding error and the antialiasing border
248*e2c1660dSHerbert 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*e2c1660dSHerbert Dürr                  Size(  static_cast<long int>(lWidth+4),
252*e2c1660dSHerbert 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 // -----------------------------------------------------------------------
301