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