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_cppcanvas.hxx"
30 #include <rtl/instance.hxx>
31 #include <osl/getglobalmutex.hxx>
32 #include <osl/diagnose.h>
33 #include <com/sun/star/rendering/InterpolationMode.hpp>
34 #include <vcl/window.hxx>
35 #include <vcl/graph.hxx>
36 #include <vcl/canvastools.hxx>
37 #include <basegfx/polygon/b2dpolypolygon.hxx>
38 
39 #include <cppcanvas/vclfactory.hxx>
40 
41 #include <implbitmapcanvas.hxx>
42 #include <implspritecanvas.hxx>
43 #include <implpolypolygon.hxx>
44 #include <implbitmap.hxx>
45 #include <implrenderer.hxx>
46 #include <impltext.hxx>
47 #include <implsprite.hxx>
48 
49 
50 using namespace ::com::sun::star;
51 
52 namespace cppcanvas
53 {
54 	/* Singleton handling */
55     struct InitInstance
56     {
57         VCLFactory* operator()()
58         {
59             return new VCLFactory();
60         }
61     };
62 
63     VCLFactory& VCLFactory::getInstance()
64     {
65         return *rtl_Instance< VCLFactory, InitInstance, ::osl::MutexGuard,
66             ::osl::GetGlobalMutex >::create(
67                 InitInstance(), ::osl::GetGlobalMutex());
68     }
69 
70     VCLFactory::VCLFactory()
71     {
72     }
73 
74     VCLFactory::~VCLFactory()
75     {
76     }
77 
78     BitmapCanvasSharedPtr VCLFactory::createCanvas( const ::Window& rVCLWindow )
79     {
80         return BitmapCanvasSharedPtr(
81             new internal::ImplBitmapCanvas(
82                 uno::Reference< rendering::XBitmapCanvas >(
83                     rVCLWindow.GetCanvas(),
84                     uno::UNO_QUERY) ) );
85     }
86 
87     BitmapCanvasSharedPtr VCLFactory::createCanvas( const uno::Reference< rendering::XBitmapCanvas >& xCanvas )
88     {
89         return BitmapCanvasSharedPtr(
90             new internal::ImplBitmapCanvas( xCanvas ) );
91     }
92 
93     SpriteCanvasSharedPtr VCLFactory::createSpriteCanvas( const ::Window& rVCLWindow ) const
94     {
95         return SpriteCanvasSharedPtr(
96             new internal::ImplSpriteCanvas(
97                 uno::Reference< rendering::XSpriteCanvas >(
98                     rVCLWindow.GetSpriteCanvas(),
99                     uno::UNO_QUERY) ) );
100     }
101 
102     SpriteCanvasSharedPtr VCLFactory::createSpriteCanvas( const uno::Reference< rendering::XSpriteCanvas >& xCanvas ) const
103     {
104         return SpriteCanvasSharedPtr(
105             new internal::ImplSpriteCanvas( xCanvas ) );
106     }
107 
108     SpriteCanvasSharedPtr VCLFactory::createFullscreenSpriteCanvas( const ::Window& rVCLWindow,
109                                                                     const Size& 	rFullscreenSize ) const
110     {
111         return SpriteCanvasSharedPtr(
112             new internal::ImplSpriteCanvas(
113                 uno::Reference< rendering::XSpriteCanvas >(
114                     rVCLWindow.GetFullscreenSpriteCanvas( rFullscreenSize ),
115                     uno::UNO_QUERY) ) );
116     }
117 
118     PolyPolygonSharedPtr VCLFactory::createPolyPolygon( const CanvasSharedPtr& 	rCanvas,
119                                                         const ::Polygon& 		rPoly ) const
120     {
121         OSL_ENSURE( rCanvas.get() != NULL &&
122                     rCanvas->getUNOCanvas().is(),
123                     "VCLFactory::createPolyPolygon(): Invalid canvas" );
124 
125         if( rCanvas.get() == NULL )
126             return PolyPolygonSharedPtr();
127 
128         uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
129         if( !xCanvas.is() )
130             return PolyPolygonSharedPtr();
131 
132         return PolyPolygonSharedPtr(
133             new internal::ImplPolyPolygon( rCanvas,
134                                            ::vcl::unotools::xPolyPolygonFromPolygon(
135                                                xCanvas->getDevice(),
136                                                rPoly) ) );
137     }
138 
139     PolyPolygonSharedPtr VCLFactory::createPolyPolygon( const CanvasSharedPtr& 	rCanvas,
140                                                         const ::PolyPolygon& 	rPolyPoly ) const
141     {
142         OSL_ENSURE( rCanvas.get() != NULL &&
143                     rCanvas->getUNOCanvas().is(),
144                     "VCLFactory::createPolyPolygon(): Invalid canvas" );
145 
146         if( rCanvas.get() == NULL )
147             return PolyPolygonSharedPtr();
148 
149         uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
150         if( !xCanvas.is() )
151             return PolyPolygonSharedPtr();
152 
153         return PolyPolygonSharedPtr(
154             new internal::ImplPolyPolygon( rCanvas,
155                                            ::vcl::unotools::xPolyPolygonFromPolyPolygon(
156                                                xCanvas->getDevice(),
157                                                rPolyPoly) ) );
158     }
159 
160     BitmapSharedPtr VCLFactory::createBitmap( const CanvasSharedPtr&	rCanvas,
161                                               const ::Size& 			rSize ) const
162     {
163         OSL_ENSURE( rCanvas.get() != NULL &&
164                     rCanvas->getUNOCanvas().is(),
165                     "VCLFactory::createBitmap(): Invalid canvas" );
166 
167         if( rCanvas.get() == NULL )
168             return BitmapSharedPtr();
169 
170         uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
171         if( !xCanvas.is() )
172             return BitmapSharedPtr();
173 
174         return BitmapSharedPtr(
175             new internal::ImplBitmap( rCanvas,
176                                       xCanvas->getDevice()->createCompatibleBitmap(
177                                           ::vcl::unotools::integerSize2DFromSize(rSize) ) ) );
178     }
179 
180     BitmapSharedPtr VCLFactory::createAlphaBitmap( const CanvasSharedPtr&	rCanvas,
181                                                    const ::Size& 			rSize ) const
182     {
183         OSL_ENSURE( rCanvas.get() != NULL &&
184                     rCanvas->getUNOCanvas().is(),
185                     "VCLFactory::createBitmap(): Invalid canvas" );
186 
187         if( rCanvas.get() == NULL )
188             return BitmapSharedPtr();
189 
190         uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
191         if( !xCanvas.is() )
192             return BitmapSharedPtr();
193 
194         return BitmapSharedPtr(
195             new internal::ImplBitmap( rCanvas,
196                                       xCanvas->getDevice()->createCompatibleAlphaBitmap(
197                                           ::vcl::unotools::integerSize2DFromSize(rSize) ) ) );
198     }
199 
200     BitmapSharedPtr VCLFactory::createBitmap( const CanvasSharedPtr& 	rCanvas,
201                                               const ::Bitmap& 			rBitmap ) const
202     {
203         OSL_ENSURE( rCanvas.get() != NULL &&
204                     rCanvas->getUNOCanvas().is(),
205                     "VCLFactory::createBitmap(): Invalid canvas" );
206 
207         if( rCanvas.get() == NULL )
208             return BitmapSharedPtr();
209 
210         uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
211         if( !xCanvas.is() )
212             return BitmapSharedPtr();
213 
214         return BitmapSharedPtr( new internal::ImplBitmap( rCanvas,
215                                                           ::vcl::unotools::xBitmapFromBitmap(
216                                                               xCanvas->getDevice(),
217                                                               rBitmap) ) );
218     }
219 
220     BitmapSharedPtr VCLFactory::createBitmap( const CanvasSharedPtr& 	rCanvas,
221                                               const ::BitmapEx& 		rBmpEx ) const
222     {
223         OSL_ENSURE( rCanvas.get() != NULL &&
224                     rCanvas->getUNOCanvas().is(),
225                     "VCLFactory::createBitmap(): Invalid canvas" );
226 
227         if( rCanvas.get() == NULL )
228             return BitmapSharedPtr();
229 
230         uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
231         if( !xCanvas.is() )
232             return BitmapSharedPtr();
233 
234         return BitmapSharedPtr( new internal::ImplBitmap( rCanvas,
235                                                           ::vcl::unotools::xBitmapFromBitmapEx(
236                                                               xCanvas->getDevice(),
237                                                               rBmpEx) ) );
238     }
239 
240     RendererSharedPtr VCLFactory::createRenderer( const CanvasSharedPtr& 		rCanvas,
241                                                   const ::Graphic& 				rGraphic,
242                                                   const Renderer::Parameters& 	rParms ) const
243     {
244         OSL_ENSURE( rCanvas.get() != NULL &&
245                     rCanvas->getUNOCanvas().is(),
246                     "VCLFactory::createRenderer(): Invalid canvas" );
247 
248         if( rCanvas.get() == NULL )
249             return RendererSharedPtr();
250 
251         uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
252         if( !xCanvas.is() )
253             return RendererSharedPtr();
254 
255         if( rGraphic.GetType() == GRAPHIC_GDIMETAFILE )
256             return RendererSharedPtr( new internal::ImplRenderer( rCanvas,
257                                                                   rGraphic.GetGDIMetaFile(),
258                                                                   rParms ) );
259         else
260             return RendererSharedPtr( new internal::ImplRenderer( rCanvas,
261                                                                   rGraphic.GetBitmapEx(),
262                                                                   rParms ) );
263     }
264 
265     RendererSharedPtr VCLFactory::createRenderer( const CanvasSharedPtr& 		rCanvas,
266                                                   const ::GDIMetaFile& 			rMtf,
267                                                   const Renderer::Parameters& 	rParms ) const
268     {
269         return RendererSharedPtr( new internal::ImplRenderer( rCanvas,
270                                                               rMtf,
271                                                               rParms ) );
272     }
273 
274     SpriteSharedPtr VCLFactory::createAnimatedSprite( const SpriteCanvasSharedPtr& rCanvas, const ::Animation& rAnim ) const
275     {
276         OSL_ENSURE( rCanvas.get() != NULL &&
277                     rCanvas->getUNOCanvas().is(),
278                     "VCLFactory::createAnimatedSprite(): Invalid canvas" );
279 
280         if( rCanvas.get() == NULL )
281             return SpriteSharedPtr();
282 
283         uno::Reference< rendering::XCanvas > xCanvas( rCanvas->getUNOCanvas() );
284         if( !xCanvas.is() )
285             return SpriteSharedPtr();
286 
287         uno::Reference< rendering::XSpriteCanvas > xSpriteCanvas( rCanvas->getUNOSpriteCanvas() );
288         if( !xSpriteCanvas.is() )
289             return SpriteSharedPtr();
290 
291         if( rAnim.IsEmpty() )
292             return SpriteSharedPtr();
293 
294         internal::ImplSpriteCanvas* pSpriteCanvas = dynamic_cast< internal::ImplSpriteCanvas* >( rCanvas.get() );
295         if( !pSpriteCanvas )
296             return SpriteSharedPtr();
297 
298         const sal_uInt16 nBitmaps( rAnim.Count() );
299         uno::Sequence< uno::Reference< rendering::XBitmap > > aBitmapSequence( nBitmaps );
300         uno::Reference< rendering::XBitmap >* pBitmaps = aBitmapSequence.getArray();
301 
302         unsigned int i;
303         BitmapEx aBmpEx;
304         BitmapEx aRestoreBuffer;
305         aBmpEx.SetSizePixel( rAnim.GetDisplaySizePixel() );
306         aRestoreBuffer.SetSizePixel( rAnim.GetDisplaySizePixel() );
307         aBmpEx.Erase( ::Color( 255, 0,0,0 ) ); // clear alpha channel
308         aRestoreBuffer = aBmpEx;
309         const Point aEmptyPoint;
310 
311         for( i=0; i<nBitmaps; ++i )
312         {
313             const AnimationBitmap& rAnimBmp( rAnim.Get((sal_uInt16)i) );
314 
315             // Handle dispose according to GIF spec: a
316             // DISPOSE_PREVIOUS does _not_ mean to revert to the
317             // previous frame, but to revert to the last frame with
318             // DISPOSE_NOT
319 
320             // dispose previous
321         	if( rAnimBmp.eDisposal == DISPOSE_BACK )
322             {
323                 // simply clear bitmap to transparent
324                 aBmpEx.Erase( ::Color( 255, 0,0,0 ) );
325             }
326     		else if( rAnimBmp.eDisposal == DISPOSE_PREVIOUS )
327             {
328                 // copy in last known full frame
329                 aBmpEx = aRestoreBuffer;
330             }
331             // I have exactly _no_ idea what DISPOSE_FULL is supposed
332             // to do. It's apparently not set anywhere in our code
333             OSL_ENSURE( rAnimBmp.eDisposal!=DISPOSE_FULL,
334                         "VCLFactory::createAnimatedSprite(): Somebody set the deprecated DISPOSE_FULL at the Animation" );
335 
336             // update display
337             aBmpEx.CopyPixel( Rectangle( rAnimBmp.aPosPix,
338                                          rAnimBmp.aSizePix ),
339                               Rectangle( aEmptyPoint,
340                                          rAnimBmp.aSizePix ),
341                               &rAnimBmp.aBmpEx );
342 
343             // store last DISPOSE_NOT frame, for later
344             // DISPOSE_PREVIOUS updates
345             if( rAnimBmp.eDisposal == DISPOSE_NOT )
346                 aRestoreBuffer = aBmpEx;
347 
348             pBitmaps[i] = ::vcl::unotools::xBitmapFromBitmapEx(
349                 xCanvas->getDevice(),
350                 aBmpEx);
351         }
352 
353         return pSpriteCanvas->createSpriteFromBitmaps( aBitmapSequence,
354                                                        rendering::InterpolationMode::NEAREST_NEIGHBOR );
355     }
356 
357     TextSharedPtr VCLFactory::createText( const CanvasSharedPtr& rCanvas, const ::rtl::OUString& rText ) const
358     {
359         return TextSharedPtr( new internal::ImplText( rCanvas,
360                                                       rText ) );
361     }
362 
363 }
364