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_basegfx.hxx" 26 27 #include "basegfx/tools/keystoplerp.hxx" 28 #include <com/sun/star/uno/Sequence.hxx> 29 30 #include <algorithm> 31 32 static void validateInput(const std::vector<double>& rKeyStops) 33 { 34 (void)rKeyStops; 35 #ifdef DBG_UTIL 36 OSL_ENSURE( rKeyStops.size() > 1, 37 "KeyStopLerp::KeyStopLerp(): key stop vector must have two entries or more" ); 38 39 // rKeyStops must be sorted in ascending order 40 for( ::std::size_t i=1, len=rKeyStops.size(); i<len; ++i ) 41 { 42 if( rKeyStops[i-1] > rKeyStops[i] ) 43 OSL_ENSURE( false, 44 "KeyStopLerp::KeyStopLerp(): time vector is not sorted in ascending order!" ); 45 } 46 #endif 47 } 48 49 namespace basegfx 50 { 51 namespace tools 52 { 53 KeyStopLerp::KeyStopLerp( const std::vector<double>& rKeyStops ) : 54 maKeyStops(rKeyStops), 55 mnLastIndex(0) 56 { 57 validateInput(maKeyStops); 58 } 59 60 KeyStopLerp::KeyStopLerp( const ::com::sun::star::uno::Sequence<double>& rKeyStops ) : 61 maKeyStops(rKeyStops.getLength()), 62 mnLastIndex(0) 63 { 64 std::copy( rKeyStops.getConstArray(), 65 rKeyStops.getConstArray()+rKeyStops.getLength(), 66 maKeyStops.begin() ); 67 validateInput(maKeyStops); 68 } 69 70 KeyStopLerp::ResultType KeyStopLerp::lerp(double fAlpha) const 71 { 72 // cached value still okay? 73 if( maKeyStops.at(mnLastIndex) < fAlpha || 74 maKeyStops.at(mnLastIndex+1) >= fAlpha ) 75 { 76 // nope, find new index 77 mnLastIndex = std::min<std::ptrdiff_t>( 78 maKeyStops.size()-2, 79 // range is ensured by max below 80 std::max<std::ptrdiff_t>( 81 0, 82 std::distance( maKeyStops.begin(), 83 std::lower_bound( maKeyStops.begin(), 84 maKeyStops.end(), 85 fAlpha )) - 1 )); 86 } 87 88 // lerp between stop and stop+1 89 const double fRawLerp= 90 (fAlpha-maKeyStops.at(mnLastIndex)) / 91 (maKeyStops.at(mnLastIndex+1) - maKeyStops.at(mnLastIndex)); 92 93 // clamp to permissible range (input fAlpha might be 94 // everything) 95 return ResultType( 96 mnLastIndex, 97 clamp(fRawLerp,0.0,1.0)); 98 } 99 } 100 } 101