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 #include <tools/diagnose_ex.h>
31 
32 #include <osl/mutex.hxx>
33 
34 #include <com/sun/star/registry/XRegistryKey.hpp>
35 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
36 #include <com/sun/star/uno/XComponentContext.hpp>
37 #include <com/sun/star/lang/NoSupportException.hpp>
38 
39 #include <toolkit/helper/vclunohelper.hxx>
40 
41 #include <basegfx/matrix/b2dhommatrix.hxx>
42 #include <basegfx/point/b2dpoint.hxx>
43 #include <basegfx/tools/canvastools.hxx>
44 #include <basegfx/numeric/ftools.hxx>
45 
46 #include "cairo_spritecanvas.hxx"
47 
48 using namespace ::cairo;
49 using namespace ::com::sun::star;
50 
51 namespace cairocanvas
52 {
SpriteCanvas(const uno::Sequence<uno::Any> & aArguments,const uno::Reference<uno::XComponentContext> & rxContext)53     SpriteCanvas::SpriteCanvas( const uno::Sequence< uno::Any >&                aArguments,
54                                 const uno::Reference< uno::XComponentContext >& rxContext ) :
55         maArguments(aArguments),
56         mxComponentContext( rxContext )
57     {
58     }
59 
initialize()60     void SpriteCanvas::initialize()
61     {
62 		VERBOSE_TRACE("CairoSpriteCanvas created %p\n", this);
63 
64         // #i64742# Only call initialize when not in probe mode
65         if( maArguments.getLength() == 0 )
66             return;
67 
68         /* maArguments:
69            0: ptr to creating instance (Window or VirtualDevice)
70            1: SystemEnvData as a streamed Any (or empty for VirtualDevice)
71            2: current bounds of creating instance
72            3: bool, denoting always on top state for Window (always false for VirtualDevice)
73            4: XWindow for creating Window (or empty for VirtualDevice)
74            5: SystemGraphicsData as a streamed Any
75          */
76         ENSURE_ARG_OR_THROW( maArguments.getLength() >= 4 &&
77                              maArguments[0].getValueTypeClass() == uno::TypeClass_HYPER &&
78                              maArguments[4].getValueTypeClass() == uno::TypeClass_INTERFACE,
79                              "CairoSpriteCanvas::initialize: wrong number of arguments, or wrong types" );
80 
81         awt::Rectangle aRect;
82         maArguments[2] >>= aRect;
83 
84         sal_Bool bIsFullscreen( sal_False );
85         maArguments[3] >>= bIsFullscreen;
86 
87         uno::Reference< awt::XWindow > xParentWindow;
88         maArguments[4] >>= xParentWindow;
89 
90         Window* pParentWindow = VCLUnoHelper::GetWindow(xParentWindow);
91         if( !pParentWindow )
92             throw lang::NoSupportException(
93                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
94                                      "Parent window not VCL window, or canvas out-of-process!")),
95                 NULL);
96 
97         bool bHasXRender = IsCairoWorking(pParentWindow);
98         ENSURE_ARG_OR_THROW( bHasXRender == true,
99                              "CairoSpriteCanvas::SpriteCanvas: No RENDER extension" );
100 
101         Size aPixelSize( pParentWindow->GetOutputSizePixel() );
102         const ::basegfx::B2ISize aSize( aPixelSize.Width(),
103                                         aPixelSize.Height() );
104 
105         ENSURE_ARG_OR_THROW( pParentWindow != NULL,
106                              "CairoSpriteCanvas::initialize: invalid Window pointer" );
107 
108         // setup helper
109         maDeviceHelper.init( *pParentWindow,
110                              *this,
111                              aSize,
112                              bIsFullscreen );
113 
114         setWindow(uno::Reference<awt::XWindow2>(xParentWindow, uno::UNO_QUERY_THROW));
115 
116         maCanvasHelper.init( maRedrawManager,
117                              *this,
118                              aSize );
119 
120         maArguments.realloc(0);
121     }
122 
disposing()123     void SAL_CALL SpriteCanvas::disposing()
124     {
125         ::osl::MutexGuard aGuard( m_aMutex );
126 
127         mxComponentContext.clear();
128 
129         // forward to parent
130         SpriteCanvasBaseT::disposing();
131     }
132 
showBuffer(::sal_Bool bUpdateAll)133     ::sal_Bool SAL_CALL SpriteCanvas::showBuffer( ::sal_Bool bUpdateAll ) throw (uno::RuntimeException)
134     {
135         return updateScreen( bUpdateAll );
136     }
137 
switchBuffer(::sal_Bool bUpdateAll)138     ::sal_Bool SAL_CALL SpriteCanvas::switchBuffer( ::sal_Bool bUpdateAll ) throw (uno::RuntimeException)
139     {
140         return updateScreen( bUpdateAll );
141     }
142 
updateScreen(sal_Bool bUpdateAll)143     sal_Bool SAL_CALL SpriteCanvas::updateScreen( sal_Bool bUpdateAll ) throw (uno::RuntimeException)
144     {
145         ::osl::MutexGuard aGuard( m_aMutex );
146 
147         // avoid repaints on hidden window (hidden: not mapped to
148         // screen). Return failure, since the screen really has _not_
149         // been updated (caller should try again later)
150         return !mbIsVisible ? false : maCanvasHelper.updateScreen(
151             ::basegfx::unotools::b2IRectangleFromAwtRectangle(maBounds),
152             bUpdateAll,
153             mbSurfaceDirty);
154     }
155 
getServiceName()156     ::rtl::OUString SAL_CALL SpriteCanvas::getServiceName(  ) throw (uno::RuntimeException)
157     {
158         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SPRITECANVAS_SERVICE_NAME ) );
159     }
160 
getSurface()161     SurfaceSharedPtr SpriteCanvas::getSurface()
162     {
163         return maDeviceHelper.getBufferSurface();
164     }
165 
createSurface(const::basegfx::B2ISize & rSize,Content aContent)166     SurfaceSharedPtr SpriteCanvas::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
167     {
168         return maDeviceHelper.createSurface( rSize, aContent );
169     }
170 
createSurface(::Bitmap & rBitmap)171     SurfaceSharedPtr SpriteCanvas::createSurface( ::Bitmap& rBitmap )
172     {
173         BitmapSystemData aData;
174         if( rBitmap.GetSystemData( aData ) ) {
175             const Size& rSize = rBitmap.GetSizePixel();
176 
177             return maDeviceHelper.createSurface( aData, rSize );
178         }
179 
180         return SurfaceSharedPtr();
181     }
182 
changeSurface(bool,bool)183     SurfaceSharedPtr SpriteCanvas::changeSurface( bool, bool )
184     {
185         // non-modifiable surface here
186         return SurfaceSharedPtr();
187     }
188 
getOutputDevice()189     OutputDevice* SpriteCanvas::getOutputDevice()
190     {
191         return maDeviceHelper.getOutputDevice();
192     }
193 
getBufferSurface()194     SurfaceSharedPtr SpriteCanvas::getBufferSurface()
195     {
196         return maDeviceHelper.getBufferSurface();
197     }
198 
getWindowSurface()199     SurfaceSharedPtr SpriteCanvas::getWindowSurface()
200     {
201         return maDeviceHelper.getWindowSurface();
202     }
203 
getSizePixel()204     const ::basegfx::B2ISize& SpriteCanvas::getSizePixel()
205     {
206         return maDeviceHelper.getSizePixel();
207     }
208 
setSizePixel(const::basegfx::B2ISize & rSize)209     void SpriteCanvas::setSizePixel( const ::basegfx::B2ISize& rSize )
210     {
211 		maCanvasHelper.setSize( rSize );
212         // re-set background surface, in case it needed recreation
213 		maCanvasHelper.setSurface( maDeviceHelper.getBufferSurface(),
214                                    false );
215     }
216 
flush()217     void SpriteCanvas::flush()
218     {
219         maDeviceHelper.flush();
220     }
221 
repaint(const SurfaceSharedPtr & pSurface,const rendering::ViewState & viewState,const rendering::RenderState & renderState)222     bool SpriteCanvas::repaint( const SurfaceSharedPtr&       pSurface,
223                                 const rendering::ViewState&   viewState,
224                                 const rendering::RenderState& renderState )
225     {
226         return maCanvasHelper.repaint( pSurface, viewState, renderState );
227     }
228 }
229