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