X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Fsrc%2Fsynfig%2Ftime.cpp;fp=synfig-core%2Fsrc%2Fsynfig%2Ftime.cpp;h=f9fae684fa5aa60543030d8eaab4a5be3b77c375;hb=a095981e18cc37a8ecc7cd237cc22b9c10329264;hp=0000000000000000000000000000000000000000;hpb=9459638ad6797b8139f1e9f0715c96076dbf0890;p=synfig.git diff --git a/synfig-core/src/synfig/time.cpp b/synfig-core/src/synfig/time.cpp new file mode 100644 index 0000000..f9fae68 --- /dev/null +++ b/synfig-core/src/synfig/time.cpp @@ -0,0 +1,324 @@ +/* === S Y N F I G ========================================================= */ +/*! \file time.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** Copyright (c) 2008 Gerco Ballintijn +** Copyright (c) 2008 Carlos López +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "time.h" +#include +#include +#include "general.h" +#include +#include +#include +#include +#include +#include + + +#ifdef WIN32 +#include +#ifndef isnan +extern "C" { int _isnan(double x); } +#define isnan _isnan +#endif +#endif + +// For some reason isnan() isn't working on macosx any more. +// This is a quick fix. +#if defined(__APPLE__) && !defined(SYNFIG_ISNAN_FIX) +#ifdef isnan +#undef isnan +#endif +inline bool isnan(double x) { return x != x; } +inline bool isnan(float x) { return x != x; } +#define SYNFIG_ISNAN_FIX 1 +#endif + + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; + +#define tolower ::tolower + +/* === M A C R O S ========================================================= */ + +/* === G L O B A L S ======================================================= */ + +/* === M E T H O D S ======================================================= */ + +Time::Time(const String &str_, float fps): + value_(0) +{ + String str(str_); + std::transform(str.begin(),str.end(),str.begin(),&tolower); + + // Start/Begin Of Time + if(str=="sot" || str=="bot") + { + operator=(begin()); + return; + } + // End Of Time + if(str=="eot") + { + operator=(end()); + return; + } + + + unsigned int pos=0; + int read; + float amount; + + // Now try to read it in the letter-abbreviated format + while(pos=str.size() || read==0) + { + // Throw up a warning if there are no units + // and the amount isn't zero. There is no need + // to warn about units if the value is zero + // it is the only case where units are irrelevant. + if(amount!=0) + synfig::warning("Time(): No unit provided in time code, assuming SECONDS (\"%s\")",str.c_str()); + value_+=amount; + return; + } + switch(str[pos]) + { + case 'h': + case 'H': + value_+=amount*3600; + break; + case 'm': + case 'M': + value_+=amount*60; + break; + case 's': + case 'S': + value_+=amount; + break; + case 'f': + case 'F': + if(fps) + value_+=amount/fps; + else + synfig::warning("Time(): Individual frames referenced, but frame rate is unknown"); + break; + case ':': + // try to read it in as a traditional time format + { + int hour,minute,second; + float frame; + if(fps && sscanf(str.c_str(),"%d:%d:%d.%f",&hour,&minute,&second,&frame)==4) + { + value_=frame/fps+(hour*3600+minute*60+second); + return; + } + + if(sscanf(str.c_str(),"%d:%d:%d",&hour,&minute,&second)==3) + { + value_=hour*3600+minute*60+second; + return; + } + } + synfig::warning("Time(): Bad time format"); + break; + + default: + value_+=amount; + synfig::warning("Time(): Unexpected character '%c' when parsing time string \"%s\"",str[pos],str.c_str()); + break; + } + pos++; + amount=0; + } +} + +String +Time::get_string(float fps, Time::Format format)const +{ + Time time(*this); + + if(time<=begin()) + return "SOT"; // Start Of Time + if(time>=end()) + return "EOT"; // End Of Time + + if(fps<0)fps=0; + + if(ceil(time.value_)-time.value_1) + { + int frame; + frame=round_to_int(time*fps); + + return strprintf("%02d:%02d:%02d.%02d",hour,minute,second,frame); + } + else + return strprintf("%02d:%02d:%02d",hour,minute,second); + } + + if (format <= FORMAT_FRAMES) + { + if (fps && fps>0) + return strprintf("%df", round_to_int(time * fps)); + else + return strprintf("%ds", round_to_int(time * 1)); + } + + String ret; + bool started = false; + + if(format<=FORMAT_FULL || hour) + { + ret+=strprintf("%dh",hour); + started = true; + } + + if(format<=FORMAT_FULL || minute) + { + if (!(format<=FORMAT_NOSPACES) && started) + ret += " "; + + ret += strprintf("%dm", minute); + started = true; + } + + if(fps && fps>1) + { + int second; + float frame; + second=time;time-=second; + frame=time*fps; + + if(format<=FORMAT_FULL || second) + { + if (!(format<=FORMAT_NOSPACES) && started) + ret += " "; + + ret += strprintf("%ds", (int)second); + started = true; + } + + if(format<=FORMAT_FULL || abs(frame) > epsilon_() || !started) + { + if (!(format<=FORMAT_NOSPACES) && started) + ret += " "; + + if(abs(frame-floor(frame) >= epsilon_())) + ret += strprintf("%0.3ff", frame); + else + ret += strprintf("%0.0ff", frame); + } + } + else + { + float second; + second=time; + if(format<=FORMAT_FULL || second || !started) + { + if (!(format<=FORMAT_NOSPACES) && started) + ret += " "; + + if(abs(second-floor(second))>=epsilon_()) + { + String seconds(strprintf("%0.8f",second)); + + // skip trailing zeros + int count = 0; + String::reverse_iterator i = seconds.rbegin(); + for ( ; (*i) == '0'; i++) + count++; + + // if we removed too many, go back one place, leaving one zero + if (*i < '0' || *i > '9') count--; + + ret += seconds.substr(0, seconds.size()-count) + "s"; + } + else + ret+=strprintf("%0.0fs",second); + } + } + + return ret; +} + +Time +Time::round(float fps)const +{ + assert(fps>0); + + value_type time(*this); + + time*=fps; + + if(abs(time-floor(time))<0.5) + return floor(time)/fps; + else + return ceil(time)/fps; +} + +#ifdef _DEBUG +const char * +Time::c_str()const +{ + return get_string().c_str(); +} +#endif + +//! \writeme +bool +Time::is_valid()const +{ + return !isnan(value_); +}