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/matrix/b2dhommatrix.hxx> 33 #include <basegfx/point/b2dpoint.hxx> 34 #include <basegfx/polygon/b2dpolygon.hxx> 35 #include <basegfx/matrix/b2dhommatrixtools.hxx> 36 #include "snakewipe.hxx" 37 #include "transitiontools.hxx" 38 39 40 namespace slideshow { 41 namespace internal { 42 43 SnakeWipe::SnakeWipe( sal_Int32 nElements, bool diagonal, bool flipOnYAxis ) 44 : m_sqrtElements( static_cast<sal_Int32>( 45 sqrt( static_cast<double>(nElements) ) ) ), 46 m_elementEdge( 1.0 / m_sqrtElements ), 47 m_diagonal(diagonal), 48 m_flipOnYAxis(flipOnYAxis) 49 { 50 } 51 52 ::basegfx::B2DPolyPolygon SnakeWipe::calcSnake( double t ) const 53 { 54 ::basegfx::B2DPolyPolygon res; 55 const double area = (t * m_sqrtElements * m_sqrtElements); 56 const sal_Int32 line_ = (static_cast<sal_Int32>(area) / m_sqrtElements); 57 const double line = ::basegfx::pruneScaleValue( 58 static_cast<double>(line_) / m_sqrtElements ); 59 const double col = ::basegfx::pruneScaleValue( 60 (area - (line_ * m_sqrtElements)) / m_sqrtElements ); 61 62 if (! ::basegfx::fTools::equalZero( line )) { 63 ::basegfx::B2DPolygon poly; 64 poly.append( ::basegfx::B2DPoint( 0.0, 0.0 ) ); 65 poly.append( ::basegfx::B2DPoint( 0.0, line ) ); 66 poly.append( ::basegfx::B2DPoint( 1.0, line ) ); 67 poly.append( ::basegfx::B2DPoint( 1.0, 0.0 ) ); 68 poly.setClosed(true); 69 res.append(poly); 70 } 71 if (! ::basegfx::fTools::equalZero( col )) 72 { 73 double offset = 0.0; 74 if ((line_ & 1) == 1) { 75 // odd line: => right to left 76 offset = (1.0 - col); 77 } 78 ::basegfx::B2DPolygon poly; 79 poly.append( ::basegfx::B2DPoint( offset, line ) ); 80 poly.append( ::basegfx::B2DPoint( offset, 81 line + m_elementEdge ) ); 82 poly.append( ::basegfx::B2DPoint( offset + col, 83 line + m_elementEdge ) ); 84 poly.append( ::basegfx::B2DPoint( offset + col, line ) ); 85 poly.setClosed(true); 86 res.append(poly); 87 } 88 89 return res; 90 } 91 92 ::basegfx::B2DPolyPolygon SnakeWipe::calcHalfDiagonalSnake( 93 double t, bool in ) const 94 { 95 ::basegfx::B2DPolyPolygon res; 96 97 if (in) { 98 const double sqrtArea2 = sqrt( t * m_sqrtElements * m_sqrtElements ); 99 const double edge = ::basegfx::pruneScaleValue( 100 static_cast<double>( static_cast<sal_Int32>(sqrtArea2) ) / 101 m_sqrtElements ); 102 103 ::basegfx::B2DPolygon poly; 104 if (! ::basegfx::fTools::equalZero( edge )) { 105 poly.append( ::basegfx::B2DPoint( 0.0, 0.0 ) ); 106 poly.append( ::basegfx::B2DPoint( 0.0, edge ) ); 107 poly.append( ::basegfx::B2DPoint( edge, 0.0 ) ); 108 poly.setClosed(true); 109 res.append(poly); 110 } 111 const double a = (M_SQRT1_2 / m_sqrtElements); 112 const double d = (sqrtArea2 - static_cast<sal_Int32>(sqrtArea2)); 113 const double len = (t * M_SQRT2 * d); 114 const double height = ::basegfx::pruneScaleValue( M_SQRT1_2 / m_sqrtElements ); 115 poly.clear(); 116 poly.append( ::basegfx::B2DPoint( 0.0, 0.0 ) ); 117 poly.append( ::basegfx::B2DPoint( 0.0, height ) ); 118 poly.append( ::basegfx::B2DPoint( len + a, height ) ); 119 poly.append( ::basegfx::B2DPoint( len + a, 0.0 ) ); 120 poly.setClosed(true); 121 ::basegfx::B2DHomMatrix aTransform; 122 123 if ((static_cast<sal_Int32>(sqrtArea2) & 1) == 1) 124 { 125 // odd line 126 aTransform = basegfx::tools::createRotateB2DHomMatrix(M_PI_2 + M_PI_4); 127 aTransform.translate(edge + m_elementEdge, 0.0); 128 } 129 else 130 { 131 aTransform = basegfx::tools::createTranslateB2DHomMatrix(-a, 0.0); 132 aTransform.rotate( -M_PI_4 ); 133 aTransform.translate( 0.0, edge ); 134 } 135 136 poly.transform( aTransform ); 137 res.append(poly); 138 } 139 else // out 140 { 141 const double sqrtArea2 = sqrt( t * m_sqrtElements * m_sqrtElements ); 142 const double edge = ::basegfx::pruneScaleValue( 143 static_cast<double>( static_cast<sal_Int32>(sqrtArea2) ) / 144 m_sqrtElements ); 145 146 ::basegfx::B2DPolygon poly; 147 if (! ::basegfx::fTools::equalZero( edge )) { 148 poly.append( ::basegfx::B2DPoint( 0.0, 1.0 ) ); 149 poly.append( ::basegfx::B2DPoint( edge, 1.0 ) ); 150 poly.append( ::basegfx::B2DPoint( 1.0, edge ) ); 151 poly.append( ::basegfx::B2DPoint( 1.0, 0.0 ) ); 152 poly.setClosed(true); 153 res.append(poly); 154 } 155 const double a = (M_SQRT1_2 / m_sqrtElements); 156 const double d = (sqrtArea2 - static_cast<sal_Int32>(sqrtArea2)); 157 const double len = ((1.0 - t) * M_SQRT2 * d); 158 const double height = ::basegfx::pruneScaleValue( M_SQRT1_2 / m_sqrtElements ); 159 poly.clear(); 160 poly.append( ::basegfx::B2DPoint( 0.0, 0.0 ) ); 161 poly.append( ::basegfx::B2DPoint( 0.0, height ) ); 162 poly.append( ::basegfx::B2DPoint( len + a, height ) ); 163 poly.append( ::basegfx::B2DPoint( len + a, 0.0 ) ); 164 poly.setClosed(true); 165 ::basegfx::B2DHomMatrix aTransform; 166 167 if ((static_cast<sal_Int32>(sqrtArea2) & 1) == 1) 168 { 169 // odd line 170 aTransform = basegfx::tools::createTranslateB2DHomMatrix(0.0, -height); 171 aTransform.rotate( M_PI_2 + M_PI_4 ); 172 aTransform.translate( 1.0, edge ); 173 } 174 else 175 { 176 aTransform = basegfx::tools::createRotateB2DHomMatrix(-M_PI_4); 177 aTransform.translate( edge, 1.0 ); 178 } 179 poly.transform( aTransform ); 180 res.append(poly); 181 } 182 183 return res; 184 } 185 186 ::basegfx::B2DPolyPolygon SnakeWipe::operator () ( double t ) 187 { 188 ::basegfx::B2DPolyPolygon res; 189 if (m_diagonal) 190 { 191 if (t >= 0.5) { 192 res.append( calcHalfDiagonalSnake( 1.0, true ) ); 193 res.append( calcHalfDiagonalSnake( 2.0 * (t - 0.5), false ) ); 194 } 195 else 196 res.append( calcHalfDiagonalSnake( 2.0 * t, true ) ); 197 } 198 else 199 res = calcSnake(t); 200 201 return m_flipOnYAxis ? flipOnYAxis(res) : res; 202 } 203 204 ::basegfx::B2DPolyPolygon ParallelSnakesWipe::operator () ( double t ) 205 { 206 ::basegfx::B2DPolyPolygon res; 207 if (m_diagonal) 208 { 209 OSL_ASSERT( m_opposite ); 210 ::basegfx::B2DPolyPolygon half( 211 calcHalfDiagonalSnake( t, false /* out */ ) ); 212 // flip on x axis and rotate 90 degrees: 213 basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleB2DHomMatrix(1.0, -1.0)); 214 aTransform.translate( -0.5, 0.5 ); 215 aTransform.rotate( M_PI_2 ); 216 aTransform.translate( 0.5, 0.5 ); 217 half.transform( aTransform ); 218 half.flip(); 219 res.append( half ); 220 221 // rotate 180 degrees: 222 aTransform = basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5); 223 aTransform.rotate( M_PI ); 224 aTransform.translate( 0.5, 0.5 ); 225 half.transform( aTransform ); 226 res.append( half ); 227 } 228 else 229 { 230 ::basegfx::B2DPolyPolygon half( calcSnake( t / 2.0 ) ); 231 // rotate 90 degrees: 232 basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5)); 233 aTransform.rotate( M_PI_2 ); 234 aTransform.translate( 0.5, 0.5 ); 235 half.transform( aTransform ); 236 res.append( flipOnYAxis(half) ); 237 res.append( m_opposite ? flipOnXAxis(half) : half ); 238 } 239 240 return m_flipOnYAxis ? flipOnYAxis(res) : res; 241 } 242 243 } 244 } 245