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