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_slideshow.hxx"
26 
27 // must be first
28 #include <canvas/debug.hxx>
29 #include <tools/diagnose_ex.h>
30 
31 #include "viewbackgroundshape.hxx"
32 #include "tools.hxx"
33 
34 #include <rtl/logfile.hxx>
35 #include <rtl/math.hxx>
36 
37 #include <comphelper/anytostring.hxx>
38 #include <cppuhelper/exc_hlp.hxx>
39 
40 #include <basegfx/polygon/b2dpolygontools.hxx>
41 #include <basegfx/polygon/b2dpolygon.hxx>
42 #include <basegfx/numeric/ftools.hxx>
43 #include <basegfx/matrix/b2dhommatrix.hxx>
44 #include <basegfx/matrix/b2dhommatrixtools.hxx>
45 
46 #include <com/sun/star/rendering/XCanvas.hpp>
47 
48 #include <canvas/verbosetrace.hxx>
49 #include <canvas/canvastools.hxx>
50 #include <cppcanvas/vclfactory.hxx>
51 #include <cppcanvas/basegfxfactory.hxx>
52 #include <cppcanvas/renderer.hxx>
53 #include <cppcanvas/bitmap.hxx>
54 
55 using namespace ::com::sun::star;
56 
57 
58 namespace slideshow
59 {
60     namespace internal
61     {
62 
prefetch(const::cppcanvas::CanvasSharedPtr & rDestinationCanvas,const GDIMetaFileSharedPtr & rMtf) const63         bool ViewBackgroundShape::prefetch( const ::cppcanvas::CanvasSharedPtr&	rDestinationCanvas,
64                                             const GDIMetaFileSharedPtr&			rMtf ) const
65         {
66             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewBackgroundShape::prefetch()" );
67             ENSURE_OR_RETURN_FALSE( rMtf,
68                                "ViewBackgroundShape::prefetch(): no valid metafile!" );
69 
70             const ::basegfx::B2DHomMatrix& rCanvasTransform(
71                 mpViewLayer->getTransformation() );
72 
73             if( !mxBitmap.is() ||
74                 rMtf != mpLastMtf ||
75                 rCanvasTransform != maLastTransformation )
76             {
77                 // buffered bitmap is invalid, re-create
78 
79                 // determine transformed page bounds
80                 ::basegfx::B2DRectangle aTmpRect;
81                 ::canvas::tools::calcTransformedRectBounds( aTmpRect,
82                                                             maBounds,
83                                                             rCanvasTransform );
84 
85                 // determine pixel size of bitmap (choose it one pixel
86                 // larger, as polygon rendering takes one pixel more
87                 // to the right and to the bottom)
88                 const ::basegfx::B2ISize aBmpSizePixel(
89                     ::basegfx::fround( aTmpRect.getRange().getX() + 1),
90                     ::basegfx::fround( aTmpRect.getRange().getY() + 1) );
91 
92                 // create a bitmap of appropriate size
93                 ::cppcanvas::BitmapSharedPtr pBitmap(
94                     ::cppcanvas::BaseGfxFactory::getInstance().createBitmap(
95                         rDestinationCanvas,
96                         aBmpSizePixel ) );
97 
98                 ENSURE_OR_THROW( pBitmap,
99                                   "ViewBackgroundShape::prefetch(): Cannot create background bitmap" );
100 
101                 ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() );
102 
103                 ENSURE_OR_THROW( pBitmapCanvas,
104                                   "ViewBackgroundShape::prefetch(): Cannot create background bitmap canvas" );
105 
106                 // clear bitmap
107                 initSlideBackground( pBitmapCanvas,
108                                      aBmpSizePixel );
109 
110                 // apply linear part of destination canvas transformation (linear means in this context:
111                 // transformation without any translational components)
112                 ::basegfx::B2DHomMatrix aLinearTransform( rCanvasTransform );
113                 aLinearTransform.set( 0, 2, 0.0 );
114                 aLinearTransform.set( 1, 2, 0.0 );
115                 pBitmapCanvas->setTransformation( aLinearTransform );
116 
117                 const basegfx::B2DHomMatrix aShapeTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(
118                     maBounds.getWidth(), maBounds.getHeight(),
119                     maBounds.getMinX(), maBounds.getMinY()));
120 
121                 ::cppcanvas::RendererSharedPtr pRenderer(
122                     ::cppcanvas::VCLFactory::getInstance().createRenderer(
123                         pBitmapCanvas,
124                         *rMtf.get(),
125                         ::cppcanvas::Renderer::Parameters() ) );
126 
127                 ENSURE_OR_RETURN_FALSE( pRenderer,
128                                    "ViewBackgroundShape::prefetch(): Could not create Renderer" );
129 
130                 pRenderer->setTransformation( aShapeTransform );
131                 pRenderer->draw();
132 
133                 mxBitmap = pBitmap->getUNOBitmap();
134             }
135 
136             mpLastMtf 			 = rMtf;
137             maLastTransformation = rCanvasTransform;
138 
139             return mxBitmap.is();
140         }
141 
ViewBackgroundShape(const ViewLayerSharedPtr & rViewLayer,const::basegfx::B2DRectangle & rShapeBounds)142         ViewBackgroundShape::ViewBackgroundShape( const ViewLayerSharedPtr& 		rViewLayer,
143                                                   const ::basegfx::B2DRectangle&	rShapeBounds ) :
144             mpViewLayer( rViewLayer ),
145             mxBitmap(),
146             mpLastMtf(),
147             maLastTransformation(),
148             maBounds( rShapeBounds )
149         {
150             ENSURE_OR_THROW( mpViewLayer, "ViewBackgroundShape::ViewBackgroundShape(): Invalid View" );
151             ENSURE_OR_THROW( mpViewLayer->getCanvas(), "ViewBackgroundShape::ViewBackgroundShape(): Invalid ViewLayer canvas" );
152         }
153 
getViewLayer() const154         ViewLayerSharedPtr ViewBackgroundShape::getViewLayer() const
155         {
156             return mpViewLayer;
157         }
158 
render(const GDIMetaFileSharedPtr & rMtf) const159         bool ViewBackgroundShape::render( const GDIMetaFileSharedPtr& rMtf ) const
160         {
161             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewBackgroundShape::draw()" );
162 
163             const ::cppcanvas::CanvasSharedPtr&	rDestinationCanvas( mpViewLayer->getCanvas() );
164 
165             if( !prefetch( rDestinationCanvas, rMtf ) )
166                 return false;
167 
168             ENSURE_OR_RETURN_FALSE( mxBitmap.is(),
169                                "ViewBackgroundShape::draw(): Invalid background bitmap" );
170 
171             ::basegfx::B2DHomMatrix aTransform( mpViewLayer->getTransformation() );
172 
173             // invert the linear part of the view transformation
174             // (i.e. the view transformation without translational
175             // components), to be able to leave the canvas
176             // transformation intact (would otherwise destroy possible
177             // clippings, as the clip polygon is relative to the view
178             // coordinate system).
179             aTransform.set(0,2, 0.0 );
180             aTransform.set(1,2, 0.0 );
181             aTransform.invert();
182 
183             rendering::RenderState aRenderState;
184             ::canvas::tools::initRenderState( aRenderState );
185 
186             ::canvas::tools::setRenderStateTransform( aRenderState, aTransform );
187 
188             try
189             {
190                 rDestinationCanvas->getUNOCanvas()->drawBitmap( mxBitmap,
191                                                                 rDestinationCanvas->getViewState(),
192                                                                 aRenderState );
193             }
194             catch( uno::Exception& )
195             {
196                 OSL_ENSURE( false,
197                             rtl::OUStringToOString(
198                                 comphelper::anyToString( cppu::getCaughtException() ),
199                                 RTL_TEXTENCODING_UTF8 ).getStr() );
200 
201                 return false;
202             }
203 
204             return true;
205         }
206 
207     }
208 }
209