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_slideshow.hxx"
30 
31 #include <canvas/debug.hxx>
32 #include <basegfx/polygon/b2dpolygon.hxx>
33 #include <basegfx/polygon/b2dpolygontools.hxx>
34 #include <basegfx/matrix/b2dhommatrix.hxx>
35 #include <basegfx/matrix/b2dhommatrixtools.hxx>
36 
37 #include <cppcanvas/spritecanvas.hxx>
38 
39 #include "combtransition.hxx"
40 
41 #include <boost/bind.hpp>
42 
43 
44 namespace slideshow {
45 namespace internal {
46 
47 namespace {
48 
49 basegfx::B2DPolyPolygon createClipPolygon(
50     const ::basegfx::B2DVector& rDirection,
51     const ::basegfx::B2DSize& rSlideSize,
52     int nNumStrips, int nOffset )
53 {
54     // create clip polygon in standard orientation (will later
55     // be rotated to match direction vector)
56     ::basegfx::B2DPolyPolygon aClipPoly;
57 
58     // create nNumStrips/2 vertical strips
59     for( int i=nOffset; i<nNumStrips; i+=2 )
60     {
61         aClipPoly.append(
62             ::basegfx::tools::createPolygonFromRect(
63                 ::basegfx::B2DRectangle( double(i)/nNumStrips, 0.0,
64                                          double(i+1)/nNumStrips, 1.0) ) );
65 
66     }
67 
68     // rotate polygons, such that the strips are parallel to
69     // the given direction vector
70     const ::basegfx::B2DVector aUpVec(0.0, 1.0);
71     basegfx::B2DHomMatrix aMatrix(basegfx::tools::createRotateAroundPoint(0.5, 0.5, aUpVec.angle( rDirection )));
72 
73     // blow up clip polygon to slide size
74     aMatrix.scale( rSlideSize.getX(),
75                    rSlideSize.getY() );
76 
77     aClipPoly.transform( aMatrix );
78 
79     return aClipPoly;
80 }
81 
82 }
83 
84 CombTransition::CombTransition(
85     boost::optional<SlideSharedPtr> const & leavingSlide,
86     const SlideSharedPtr&                   pEnteringSlide,
87     const SoundPlayerSharedPtr&             pSoundPlayer,
88     const UnoViewContainer&                 rViewContainer,
89     ScreenUpdater&                          rScreenUpdater,
90     EventMultiplexer&                       rEventMultiplexer,
91     const ::basegfx::B2DVector&             rPushDirection,
92     sal_Int32                               nNumStripes )
93     : SlideChangeBase( leavingSlide, pEnteringSlide, pSoundPlayer,
94                        rViewContainer, rScreenUpdater, rEventMultiplexer,
95                        false /* no leaving sprite */,
96                        false /* no entering sprite */ ),
97       maPushDirectionUnit( rPushDirection ),
98       mnNumStripes( nNumStripes )
99 {
100 }
101 
102 void CombTransition::renderComb( double           t,
103                                  const ViewEntry& rViewEntry ) const
104 {
105     const SlideBitmapSharedPtr& pEnteringBitmap = getEnteringBitmap(rViewEntry);
106     const cppcanvas::CanvasSharedPtr pCanvas_ = rViewEntry.mpView->getCanvas();
107 
108     if( !pEnteringBitmap || !pCanvas_ )
109         return;
110 
111     // calc bitmap offsets. The enter/leaving bitmaps are only
112     // as large as the actual slides. For scaled-down
113     // presentations, we have to move the left, top edge of
114     // those bitmaps to the actual position, governed by the
115     // given view transform. The aBitmapPosPixel local
116     // variable is already in device coordinate space
117     // (i.e. pixel).
118 
119     // TODO(F2): Properly respect clip here. Might have to be transformed, too.
120     const basegfx::B2DHomMatrix viewTransform( rViewEntry.mpView->getTransformation() );
121     const basegfx::B2DPoint pageOrigin( viewTransform * basegfx::B2DPoint() );
122 
123     // change transformation on cloned canvas to be in
124     // device pixel
125     cppcanvas::CanvasSharedPtr pCanvas( pCanvas_->clone() );
126     basegfx::B2DPoint p;
127 
128     // TODO(Q2): Use basegfx bitmaps here
129     // TODO(F1): SlideBitmap is not fully portable between different canvases!
130 
131     const basegfx::B2DSize enteringSizePixel(
132         getEnteringSlideSizePixel( rViewEntry.mpView) );
133 
134     const basegfx::B2DVector aPushDirection = basegfx::B2DVector(
135         enteringSizePixel * maPushDirectionUnit );
136     const basegfx::B2DPolyPolygon aClipPolygon1 = basegfx::B2DPolyPolygon(
137         createClipPolygon( maPushDirectionUnit,
138                            enteringSizePixel,
139                            mnNumStripes, 0 ) );
140     const basegfx::B2DPolyPolygon aClipPolygon2 = basegfx::B2DPolyPolygon(
141         createClipPolygon( maPushDirectionUnit,
142                            enteringSizePixel,
143                            mnNumStripes, 1 ) );
144 
145     SlideBitmapSharedPtr const & pLeavingBitmap = getLeavingBitmap(rViewEntry);
146     if( pLeavingBitmap )
147     {
148         // render odd strips:
149         pLeavingBitmap->clip( aClipPolygon1 );
150         // don't modify bitmap object (no move!):
151         p = basegfx::B2DPoint( pageOrigin + (t * aPushDirection) );
152         pCanvas->setTransformation(basegfx::tools::createTranslateB2DHomMatrix(p.getX(), p.getY()));
153         pLeavingBitmap->draw( pCanvas );
154 
155         // render even strips:
156         pLeavingBitmap->clip( aClipPolygon2 );
157         // don't modify bitmap object (no move!):
158         p = basegfx::B2DPoint( pageOrigin - (t * aPushDirection) );
159         pCanvas->setTransformation(basegfx::tools::createTranslateB2DHomMatrix(p.getX(), p.getY()));
160         pLeavingBitmap->draw( pCanvas );
161     }
162 
163     // TODO(Q2): Use basegfx bitmaps here
164     // TODO(F1): SlideBitmap is not fully portable between different canvases!
165 
166     // render odd strips:
167     pEnteringBitmap->clip( aClipPolygon1 );
168     // don't modify bitmap object (no move!):
169     p = basegfx::B2DPoint( pageOrigin + ((t - 1.0) * aPushDirection) );
170     pCanvas->setTransformation(basegfx::tools::createTranslateB2DHomMatrix(p.getX(), p.getY()));
171     pEnteringBitmap->draw( pCanvas );
172 
173     // render even strips:
174     pEnteringBitmap->clip( aClipPolygon2 );
175     // don't modify bitmap object (no move!):
176     p = basegfx::B2DPoint( pageOrigin + ((1.0 - t) * aPushDirection) );
177     pCanvas->setTransformation(basegfx::tools::createTranslateB2DHomMatrix(p.getX(), p.getY()));
178     pEnteringBitmap->draw( pCanvas );
179 }
180 
181 bool CombTransition::operator()( double t )
182 {
183     std::for_each( beginViews(),
184                    endViews(),
185                    boost::bind( &CombTransition::renderComb,
186                                 this,
187                                 t,
188                                 _1 ));
189 
190     getScreenUpdater().notifyUpdate();
191 
192     return true;
193 }
194 
195 } // namespace internal
196 } // namespace presentation
197