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_canvas.hxx"
30 
31 #include <canvas/debug.hxx>
32 #include <canvas/verbosetrace.hxx>
33 #include <canvas/canvastools.hxx>
34 
35 #include <osl/mutex.hxx>
36 #include <cppuhelper/compbase1.hxx>
37 
38 #include <com/sun/star/lang/NoSupportException.hpp>
39 
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <basegfx/tools/canvastools.hxx>
42 #include <basegfx/tools/unopolypolygon.hxx>
43 
44 #include <vcl/canvastools.hxx>
45 
46 #include <tools/stream.hxx>
47 
48 #include "cairo_spritecanvas.hxx"
49 #include "cairo_canvasbitmap.hxx"
50 #include "cairo_devicehelper.hxx"
51 
52 using namespace ::cairo;
53 using namespace ::com::sun::star;
54 
55 namespace cairocanvas
56 {
57     DeviceHelper::DeviceHelper() :
58         mpSurfaceProvider( NULL ),
59         mpRefDevice( NULL ),
60         mpSurface()
61     {
62     }
63 
64     void DeviceHelper::implInit( SurfaceProvider& rSurfaceProvider,
65                                  OutputDevice&    rRefDevice )
66     {
67         mpSurfaceProvider = &rSurfaceProvider;
68         mpRefDevice = &rRefDevice;
69 
70         // no own surface, this is handled by derived classes
71     }
72 
73     void DeviceHelper::init( SurfaceProvider& rSurfaceProvider,
74                              OutputDevice&    rRefDevice )
75     {
76         implInit(rSurfaceProvider, rRefDevice);
77 
78         OutputDevice* pOutDev=getOutputDevice();
79         mpSurface = cairo::createSurface( *pOutDev,
80                                           pOutDev->GetOutOffXPixel(),
81                                           pOutDev->GetOutOffYPixel(),
82                                           pOutDev->GetOutputWidthPixel(),
83                                           pOutDev->GetOutputHeightPixel() );
84     }
85 
86     void DeviceHelper::disposing()
87     {
88         // release all references
89         mpSurface.reset();
90         mpRefDevice = NULL;
91         mpSurfaceProvider = NULL;
92     }
93 
94     void DeviceHelper::setSize( const ::basegfx::B2ISize& rSize )
95     {
96 		OSL_TRACE("DeviceHelper::setSize(): device size %d x %d", rSize.getX(), rSize.getY() );
97 
98         if( !mpRefDevice )
99             return; // disposed
100 
101         OutputDevice* pOutDev=getOutputDevice();
102 
103 #if defined (UNX) && !defined (QUARTZ)
104         // X11 only
105 		if( mpSurface )
106 			mpSurface->Resize( rSize.getX() + pOutDev->GetOutOffXPixel(),
107                                rSize.getY() + pOutDev->GetOutOffYPixel() );
108         else
109 #endif
110 			mpSurface = cairo::createSurface(
111                 *pOutDev,
112                 pOutDev->GetOutOffXPixel(),
113                 pOutDev->GetOutOffYPixel(),
114                 rSize.getX(), rSize.getY() );
115     }
116 
117     geometry::RealSize2D DeviceHelper::getPhysicalResolution()
118     {
119         // Map a one-by-one millimeter box to pixel
120         const MapMode aOldMapMode( mpRefDevice->GetMapMode() );
121         mpRefDevice->SetMapMode( MapMode(MAP_MM) );
122         const Size aPixelSize( mpRefDevice->LogicToPixel(Size(1,1)) );
123         mpRefDevice->SetMapMode( aOldMapMode );
124 
125         return ::vcl::unotools::size2DFromSize( aPixelSize );
126     }
127 
128     geometry::RealSize2D DeviceHelper::getPhysicalSize()
129     {
130         if( !mpRefDevice )
131             return ::canvas::tools::createInfiniteSize2D(); // we're disposed
132 
133         // Map the pixel dimensions of the output window to millimeter
134         const MapMode aOldMapMode( mpRefDevice->GetMapMode() );
135         mpRefDevice->SetMapMode( MapMode(MAP_MM) );
136         const Size aLogSize( mpRefDevice->PixelToLogic(mpRefDevice->GetOutputSizePixel()) );
137         mpRefDevice->SetMapMode( aOldMapMode );
138 
139         return ::vcl::unotools::size2DFromSize( aLogSize );
140     }
141 
142     uno::Reference< rendering::XLinePolyPolygon2D > DeviceHelper::createCompatibleLinePolyPolygon(
143         const uno::Reference< rendering::XGraphicDevice >& 				,
144         const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >&	points )
145     {
146         // disposed?
147         if( !mpSurfaceProvider )
148             return uno::Reference< rendering::XLinePolyPolygon2D >(); // we're disposed
149 
150         return uno::Reference< rendering::XLinePolyPolygon2D >(
151             new ::basegfx::unotools::UnoPolyPolygon(
152                 ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points ) ) );
153     }
154 
155     uno::Reference< rendering::XBezierPolyPolygon2D > DeviceHelper::createCompatibleBezierPolyPolygon(
156         const uno::Reference< rendering::XGraphicDevice >& 						,
157         const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >&	points )
158     {
159         // disposed?
160         if( !mpSurfaceProvider )
161             return uno::Reference< rendering::XBezierPolyPolygon2D >(); // we're disposed
162 
163         return uno::Reference< rendering::XBezierPolyPolygon2D >(
164             new ::basegfx::unotools::UnoPolyPolygon(
165                 ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
166     }
167 
168     uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleBitmap(
169         const uno::Reference< rendering::XGraphicDevice >& 	rDevice,
170         const geometry::IntegerSize2D& 						size )
171     {
172         // disposed?
173         if( !mpSurfaceProvider )
174             return uno::Reference< rendering::XBitmap >(); // we're disposed
175 
176         return uno::Reference< rendering::XBitmap >(
177             new CanvasBitmap(
178                 ::basegfx::unotools::b2ISizeFromIntegerSize2D( size ),
179                 SurfaceProviderRef(mpSurfaceProvider),
180                 rDevice.get(),
181                 false ));
182     }
183 
184     uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileBitmap(
185         const uno::Reference< rendering::XGraphicDevice >& 	,
186         const geometry::IntegerSize2D& 						/*size*/ )
187     {
188         return uno::Reference< rendering::XVolatileBitmap >();
189     }
190 
191     uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleAlphaBitmap(
192         const uno::Reference< rendering::XGraphicDevice >& 	rDevice,
193         const geometry::IntegerSize2D& 						size )
194     {
195         // disposed?
196         if( !mpSurfaceProvider )
197             return uno::Reference< rendering::XBitmap >(); // we're disposed
198 
199         return uno::Reference< rendering::XBitmap >(
200             new CanvasBitmap(
201                 ::basegfx::unotools::b2ISizeFromIntegerSize2D( size ),
202                 SurfaceProviderRef(mpSurfaceProvider),
203                 rDevice.get(),
204                 true ));
205     }
206 
207     uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileAlphaBitmap(
208         const uno::Reference< rendering::XGraphicDevice >& 	,
209         const geometry::IntegerSize2D& 						/*size*/ )
210     {
211         return uno::Reference< rendering::XVolatileBitmap >();
212     }
213 
214     sal_Bool DeviceHelper::hasFullScreenMode()
215     {
216         // TODO(F3): offer fullscreen mode the XCanvas way
217         return false;
218     }
219 
220     sal_Bool DeviceHelper::enterFullScreenMode( sal_Bool /*bEnter*/ )
221     {
222         // TODO(F3): offer fullscreen mode the XCanvas way
223         return false;
224     }
225 
226     uno::Any DeviceHelper::isAccelerated() const
227     {
228         return ::com::sun::star::uno::makeAny(false);
229     }
230 
231     uno::Any DeviceHelper::getDeviceHandle() const
232     {
233         return uno::makeAny( reinterpret_cast< sal_Int64 >(mpRefDevice) );
234     }
235 
236     uno::Any DeviceHelper::getSurfaceHandle() const
237     {
238         return uno::Any();
239     }
240 
241     namespace
242     {
243         struct DeviceColorSpace: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
244                                                             DeviceColorSpace>
245         {
246             uno::Reference<rendering::XColorSpace> operator()()
247             {
248                 return vcl::unotools::createStandardColorSpace();
249             }
250         };
251     }
252 
253     uno::Reference<rendering::XColorSpace> DeviceHelper::getColorSpace() const
254     {
255         // always the same
256         return DeviceColorSpace::get();
257     }
258 
259     void DeviceHelper::dumpScreenContent() const
260     {
261         static sal_uInt32 nFilePostfixCount(0);
262 
263         if( mpRefDevice )
264         {
265             String aFilename( String::CreateFromAscii("dbg_frontbuffer") );
266             aFilename += String::CreateFromInt32(nFilePostfixCount);
267             aFilename += String::CreateFromAscii(".bmp");
268 
269             SvFileStream aStream( aFilename, STREAM_STD_READWRITE );
270 
271             const ::Point aEmptyPoint;
272             bool bOldMap( mpRefDevice->IsMapModeEnabled() );
273             mpRefDevice->EnableMapMode( sal_False );
274             aStream << mpRefDevice->GetBitmap(aEmptyPoint,
275                                               mpRefDevice->GetOutputSizePixel());
276             mpRefDevice->EnableMapMode( bOldMap );
277 
278             ++nFilePostfixCount;
279         }
280     }
281 
282     SurfaceSharedPtr DeviceHelper::getSurface()
283     {
284         return mpSurface;
285     }
286 
287     SurfaceSharedPtr DeviceHelper::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
288     {
289 		if( mpSurface )
290 			return mpSurface->getSimilar( aContent, rSize.getX(), rSize.getY() );
291 
292 		return SurfaceSharedPtr();
293     }
294 
295     SurfaceSharedPtr DeviceHelper::createSurface( BitmapSystemData& rData, const Size& rSize )
296     {
297         if( mpRefDevice )
298             return createBitmapSurface( *mpRefDevice, rData, rSize );
299 
300         return SurfaceSharedPtr();
301     }
302 }
303