Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : // must be first
22 : #include <canvas/debug.hxx>
23 : #include <tools/diagnose_ex.h>
24 :
25 : #include <animatedsprite.hxx>
26 :
27 : #include <cppcanvas/canvas.hxx>
28 : #include <canvas/canvastools.hxx>
29 :
30 : #include <basegfx/vector/b2dvector.hxx>
31 : #include <basegfx/point/b2dpoint.hxx>
32 : #include <basegfx/matrix/b2dhommatrix.hxx>
33 : #include <basegfx/numeric/ftools.hxx>
34 :
35 :
36 : using namespace ::com::sun::star;
37 :
38 : namespace slideshow
39 : {
40 : namespace internal
41 : {
42 0 : AnimatedSprite::AnimatedSprite( const ViewLayerSharedPtr& rViewLayer,
43 : const ::basegfx::B2DSize& rSpriteSizePixel,
44 : double nSpritePrio ) :
45 : mpViewLayer( rViewLayer ),
46 : mpSprite(),
47 : maEffectiveSpriteSizePixel( rSpriteSizePixel ),
48 : maContentPixelOffset(),
49 : mnSpritePrio(nSpritePrio),
50 : mnAlpha(0.0),
51 : maPosPixel(),
52 : maClip(),
53 : maTransform(),
54 0 : mbSpriteVisible( false )
55 : {
56 0 : ENSURE_OR_THROW( mpViewLayer, "AnimatedSprite::AnimatedSprite(): Invalid view layer" );
57 :
58 : // Add half a pixel tolerance to sprite size, since we later on compare
59 : // against it in resize(). And view transformations will almost never yield
60 : // the same data bits when transforming to device coordinates
61 0 : maEffectiveSpriteSizePixel += ::basegfx::B2DSize(0.5, 0.5);
62 :
63 0 : mpSprite = mpViewLayer->createSprite( maEffectiveSpriteSizePixel,
64 0 : mnSpritePrio );
65 :
66 0 : ENSURE_OR_THROW( mpSprite, "AnimatedSprite::AnimatedSprite(): Could not create sprite" );
67 0 : }
68 :
69 0 : ::cppcanvas::CanvasSharedPtr AnimatedSprite::getContentCanvas() const
70 : {
71 0 : ENSURE_OR_THROW( mpViewLayer->getCanvas(), "AnimatedSprite::getContentCanvas(): No view layer canvas" );
72 :
73 0 : const ::cppcanvas::CanvasSharedPtr pContentCanvas( mpSprite->getContentCanvas() );
74 0 : pContentCanvas->clear();
75 :
76 : // extract linear part of canvas view transformation
77 : // (linear means: without translational components). The
78 : // only translation that is imposed at the view transform
79 : // is the local content pixel offset.
80 :
81 : // We can apply that directly here, no need to call
82 : // aLinearTransform.translate(), since, as said above, the
83 : // last column of aLinearTransform is assumed [0 0 1]
84 0 : ::basegfx::B2DHomMatrix aLinearTransform( mpViewLayer->getTransformation() );
85 0 : aLinearTransform.set( 0, 2, maContentPixelOffset.getX() );
86 0 : aLinearTransform.set( 1, 2, maContentPixelOffset.getY() );
87 :
88 : // apply linear part of canvas view transformation to sprite canvas
89 0 : pContentCanvas->setTransformation( aLinearTransform );
90 :
91 0 : return pContentCanvas;
92 : }
93 :
94 0 : bool AnimatedSprite::resize( const ::basegfx::B2DSize& rSpriteSizePixel )
95 : {
96 : // Enlarge or reduce the sprite size, if necessary. This
97 : // method employs a strategy similar to container, when
98 : // allocating memory: size is doubled or halved every time
99 : // the limit is reached. This makes for amortized constant
100 : // time in runtime complexity. Note that we take exact
101 : // powers of two here, since several HW-accelerated canvas
102 : // implementations are limited to such sprite sizes
103 : // (otherwise, those implementations would internally
104 : // round up, too, wasting precious mem).
105 0 : ::basegfx::B2DSize aNewSize( maEffectiveSpriteSizePixel );
106 0 : bool bNeedResize( false );
107 :
108 0 : if( rSpriteSizePixel.getX() > maEffectiveSpriteSizePixel.getX() ||
109 0 : rSpriteSizePixel.getX() < 0.5*maEffectiveSpriteSizePixel.getX() )
110 : {
111 : // enlarge or shrink width
112 0 : aNewSize.setX( ::canvas::tools::nextPow2( ::basegfx::fround(rSpriteSizePixel.getX()) ) );
113 0 : bNeedResize = true;
114 : }
115 :
116 0 : if( rSpriteSizePixel.getY() > maEffectiveSpriteSizePixel.getY() ||
117 0 : rSpriteSizePixel.getY() < 0.5*maEffectiveSpriteSizePixel.getY() )
118 : {
119 : // enlarge or shrink height, by doubling it
120 0 : aNewSize.setY( ::canvas::tools::nextPow2( ::basegfx::fround(rSpriteSizePixel.getY()) ) );
121 0 : bNeedResize = true;
122 : }
123 :
124 0 : if( bNeedResize )
125 : {
126 : // as the old sprite might have already been altered
127 : // (and therefore been placed in the update list of
128 : // the spritecanvas for this frame), must hide it
129 : // here, to ensure it's not visible on screen any
130 : // longer.
131 0 : mpSprite->hide();
132 :
133 0 : maEffectiveSpriteSizePixel = aNewSize;
134 0 : mpSprite = mpViewLayer->createSprite( maEffectiveSpriteSizePixel,
135 0 : mnSpritePrio );
136 :
137 0 : ENSURE_OR_THROW( mpSprite,
138 : "AnimatedSprite::resize(): Could not create new sprite" );
139 :
140 : // set attributes similar to previous sprite
141 0 : if( mpSprite && mbSpriteVisible )
142 : {
143 0 : mpSprite->show();
144 0 : mpSprite->setAlpha( mnAlpha );
145 :
146 0 : if( maPosPixel )
147 0 : mpSprite->movePixel( *maPosPixel );
148 :
149 0 : if( maClip )
150 0 : mpSprite->setClip( *maClip );
151 : }
152 : }
153 :
154 0 : return static_cast< bool >(mpSprite);
155 : }
156 :
157 0 : void AnimatedSprite::setPixelOffset( const ::basegfx::B2DSize& rPixelOffset )
158 : {
159 0 : maContentPixelOffset = rPixelOffset;
160 0 : }
161 :
162 0 : void AnimatedSprite::movePixel( const ::basegfx::B2DPoint& rNewPos )
163 : {
164 0 : maPosPixel.reset( rNewPos );
165 0 : mpSprite->movePixel( rNewPos );
166 0 : }
167 :
168 0 : void AnimatedSprite::setAlpha( double nAlpha )
169 : {
170 0 : mnAlpha = nAlpha;
171 0 : mpSprite->setAlpha( nAlpha );
172 0 : }
173 :
174 0 : void AnimatedSprite::clip( const ::basegfx::B2DPolyPolygon& rClip )
175 : {
176 0 : maClip.reset( rClip );
177 0 : mpSprite->setClipPixel( rClip );
178 0 : }
179 :
180 0 : void AnimatedSprite::clip()
181 : {
182 0 : maClip.reset();
183 0 : mpSprite->setClip();
184 0 : }
185 :
186 0 : void AnimatedSprite::transform( const ::basegfx::B2DHomMatrix& rTransform )
187 : {
188 0 : maTransform.reset( rTransform );
189 0 : mpSprite->transform( rTransform );
190 0 : }
191 :
192 0 : void AnimatedSprite::hide()
193 : {
194 0 : mpSprite->hide();
195 0 : mbSpriteVisible = false;
196 0 : }
197 :
198 0 : void AnimatedSprite::show()
199 : {
200 0 : mbSpriteVisible = true;
201 0 : mpSprite->show();
202 0 : }
203 :
204 : }
205 : }
206 :
207 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|