// $Id: timespan.cpp 751 2006-03-31 15:43:49Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are 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. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ #include "camtypes.h" #include "timespan.h" CC_IMPLEMENT_DYNAMIC(TimeSpan, CCObject) // We want better memory tracking #define new CAM_DEBUG_NEW /******************************************************************************************** > TimeSpan::TimeSpan() Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Purpose: Constructs an empty TimeSpan object. ********************************************************************************************/ TimeSpan::TimeSpan() { LO=HI=0; } /******************************************************************************************** > TimeSpan::TimeSpan(TimeSlice lower, TimeSlice upper) Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: lower = a lower bound time to inherit upper = an upper bound time to inherit Purpose: Constructs an bounded TimeSpan object. ********************************************************************************************/ TimeSpan::TimeSpan(TimeSlice lower, TimeSlice upper) { if (!SetBounds(lower,upper)) { ERROR3("TimeSpan() constructor called with invalid bounds") } } /******************************************************************************************** > TimeSpan::TimeSpan(const TimeSpan &other) Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: other = a reference to another time span Purpose: Copy contructor for the TimeSpan object ********************************************************************************************/ TimeSpan::TimeSpan(const TimeSpan &other) { (*this)=other; } /******************************************************************************************** > BOOL TimeSpan::SetBounds(TimeSlice lower, TimeSlice upper) Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: lower = a lower bound time to inherit upper = an upper bound time to inherit Returns: TRUE if the bounds we valid, FALSE if not. (invalid bounds means lower>=upper indicating an empty span) Purpose: Set the bounds of this time span object. The bounds are always set in the object even if they are invalid. ********************************************************************************************/ BOOL TimeSpan::SetBounds(TimeSlice lower, TimeSlice upper) { LO = lower; HI = upper; return (lower inline TimeSlice TimeSpan::GetLowerBound() const > inline TimeSlice TimeSpan::Lo() const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: - Returns: The lower bound of this TimeSpan object Purpose: Dig out the lower bound of this TimeSpan object Errors: Generates an error3 if this object is empty ********************************************************************************************/ inline TimeSlice TimeSpan::GetLowerBound() const { ERROR3IF(IsEmpty(), "TimeSpan::GetLowerBound() called on an empty TimeSpan"); return LO; } inline TimeSlice TimeSpan::Lo() const { ERROR3IF(IsEmpty(), "TimeSpan::Lo() called on an empty TimeSpan"); return LO; } /******************************************************************************************** > inline TimeSlice TimeSpan::GetUpperBound() const inline TimeSlice TimeSpan::Hi() const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: - Returns: The upper bound of this TimeSpan object Purpose: Dig out the upper bound of this TimeSpan object. It should always be greater than or equal to the lower bound, otherwise this span is invalid Errors: Generates an error3 if this object is invalid ********************************************************************************************/ inline TimeSlice TimeSpan::GetUpperBound() const { ERROR3IF(IsEmpty(), "TimeSpan::GetUpperBound() called on an empty TimeSpan"); return HI; } inline TimeSlice TimeSpan::Hi() const { ERROR3IF(IsEmpty(), "TimeSpan::Hi() called on an empty TimeSpan"); return HI; } /******************************************************************************************** > void TimeSpan::SetCreationTimeFrame(const DocView *pView, const Document *pDoc) Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: pView = a view pointer pDoc = a document pointer Purpose: Set the lower and upper time span bounds to the view's now and the documents max time. ********************************************************************************************/ /* void TimeSpan::SetCreationTimeFrame(const DocView *pView, const Document *pDoc) { ERROR3IF(pView==NULL,"NULL view pointer passed to SetCreationTimeFrame"); ERROR3IF(pDoc ==NULL,"NULL doc pointer passed to SetCreationTimeFrame"); LO = pView->GetCurrentTime(); HI = pDoc->GetUpperTimeBound(); valid=(LO<=HI); ERROR3IF(!valid, "TimeSpan::SetCreationTimeFrame() has failed to set a valid time frame!"); } */ /******************************************************************************************** > void TimeSpan::MakeInvalid() Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: - Purpose: Make this time span invalid. ********************************************************************************************/ void TimeSpan::MakeInvalid() { LO=HI; } /******************************************************************************************** > BOOL TimeSpan::IsEmpty() const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: - Returns: TRUE if this time span object is empty, i.e. it contains a lower and upper time such that lower>=upper. FALSE if these conditions are not met. Purpose: Check whether this time span object contains a non empty time frame. A time span becomes empty as a result of trying to perform boolean operations on time spans resulting in empty spans. ********************************************************************************************/ inline BOOL TimeSpan::IsEmpty() const { return (LO>=HI); } /******************************************************************************************** > BOOL TimeSpan::IsSameAs(const TimeSpan &other) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: other = a reference to another TimeSpan object Returns: TRUE if other contains the same time span as this and they are both none empty TRUE if other and this object are both empty FALSE if neither of these conditions hold Purpose: Check whether two TimeSpan objects are the same. ********************************************************************************************/ BOOL TimeSpan::IsSameAs(const TimeSpan &other) const { BOOL same = (IsEmpty() == other.IsEmpty()); if (!IsEmpty() && same) { same = same && (LO == other.GetLowerBound()); same = same && (HI == other.GetUpperBound()); } return same; } /******************************************************************************************** > TimeSpan TimeSpan::Union(const TimeSpan &other) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: other = a reference to another TimeSpan object Returns: the union of the two time spans Purpose: Find the union of this span with the other span. This union will always be valid if either or both spans are non empty ********************************************************************************************/ TimeSpan TimeSpan::Union(const TimeSpan &other) const { return (*this)+other; } /******************************************************************************************** > TimeSpan TimeSpan::Intersection(const TimeSpan &other) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: other = a reference to another TimeSpan object Returns: the intersection of the two time spans Purpose: Find the intersection of this span with 'other' span. If the intersection does not exist, either because one of the spans is empty or both spans are valid but they don't intersect then an empty timespan object is returned. Otherwise the intersection is returned ********************************************************************************************/ TimeSpan TimeSpan::Intersection(const TimeSpan &other) const { return (*this)-other; } /******************************************************************************************** > BOOL TimeSpan::IsIntersectedWith(const TimeSpan &other) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: other = a reference to another TimeSpan Returns: TRUE if this time span does intersect with the 'other' time span Purpose: Determine if this time span is intersected with the time span supplied SeeAlso: TimeSpan::Intersection() ********************************************************************************************/ BOOL TimeSpan::IsIntersectedWith(const TimeSpan &other) const { // both bounds must be valid for an intersection if (IsEmpty() || other.IsEmpty()) return FALSE; // check for none intersection case TimeSlice lower = other.GetLowerBound(); TimeSlice upper = other.GetUpperBound(); return !(upperHI); } /******************************************************************************************** > BOOL TimeSpan::InBounds(TimeSlice current) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A time slice Returns: TRUE then current is within the bounds of this time span Purpose: Checks whether the given time slice is within the bounds of this span ********************************************************************************************/ BOOL TimeSpan::InBounds(TimeSlice current) const { // Although Lo>Hi will return false always, lo==hi==current will return true // on an empty time span so check this. if (IsEmpty()) return FALSE; return (LO<=current && current<=HI); } /******************************************************************************************** > BOOL TimeSpan::Contains(const TimeSpan& other) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A reference to another timespan Returns: TRUE then other is contained entirely within this time span FALSE if not. Other may still intersect this time span. Purpose: Check wether the time span expressed by 'other' is contained entirely within this time span ********************************************************************************************/ BOOL TimeSpan::Contains(const TimeSpan& other) const { // A.Contains(Empty(B))? Empty(A).Contains(B)? if (IsEmpty() || other.IsEmpty()) return FALSE; return (LO<=other.GetLowerBound() && HI>=other.GetUpperBound()); } /******************************************************************************************** > void TimeSpan::Inflate(TimeSlice inflate) Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A reference to the inflation value Returns: - Purpose: Inflates the bounds of this object by 'inflate' ********************************************************************************************/ void TimeSpan::Inflate(TimeSlice inflate) { ERROR3IF(IsEmpty(),"TimeSpan::Inflate() called on an empty span"); LO-=inflate; HI+=inflate; } /******************************************************************************************** > double TimeSpan::GetRelativeTime(TimeSlice current) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A current time to make relative Returns: A relative time Purpose: Convert the absolute time 'current' into a relative value. If the current value is within this time span then the double result will lie between 0 and 1, otherwise it will lie somewhere on the real line. ********************************************************************************************/ inline double TimeSpan::GetRelativeTime(TimeSlice current) const { ERROR3IF(IsEmpty(),"TimeSpan::GetRelativeTime() called on an empty span"); return ((double)(LO-current)) / ((double)(HI-LO)); } /******************************************************************************************** > inline TimeSlice TimeSpan::GetAbsoluteTime(double current) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A relative time to make absolute Returns: An absolute time Purpose: Convert the relative time 'current' into an absolute value. Performs a linear interpolation on this timespans start and end times. Hence if 0<=current<=1 then the returned time will be somewhere within this time span. ********************************************************************************************/ inline TimeSlice TimeSpan::GetAbsoluteTime(double current) const { ERROR3IF(IsEmpty(),"TimeSpan::GetAbsoluteTime() called on an empty span"); return (LO + (TimeSlice)(0.5+current*((double)(HI-LO)))); } /******************************************************************************************** > TimeSpan TimeSpan::operator+(TimeSlice value) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A reference to the TimeSlice value to add to both lower and upper bounds Returns: The new shifted time span Purpose: Returns TimeSpanA = TimeSpanB + TimeSlice ********************************************************************************************/ TimeSpan TimeSpan::operator+(TimeSlice value) const { return TimeSpan(LO+value, HI+value); } /******************************************************************************************** > TimeSpan TimeSpan::operator+(const TimeSpan& other) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A reference to a rhs TimeSpan value to add to this time span Returns: A new time span holding the result of the addition ( a union ) Purpose: Overload operator+ to perform a union opertion. ********************************************************************************************/ TimeSpan TimeSpan::operator+(const TimeSpan& other) const { // is this empty? if (IsEmpty()) return other; if (other.IsEmpty()) return (*this); // make a union out of the bounds TimeSlice lower = other.GetLowerBound(); TimeSlice upper = other.GetUpperBound(); if (LOupper) upper=HI; return TimeSpan(lower,upper); } /******************************************************************************************** > TimeSpan TimeSpan::operator-(TimeSlice value) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A reference to the TimeSlice value to add to both lower and upper bounds Returns: A resulting time span Purpose: Subtracts 'value' from the bounds of this timespan and returns the result as a new time span. ********************************************************************************************/ TimeSpan TimeSpan::operator-(TimeSlice value) const { return TimeSpan(LO-value, HI-value); } /******************************************************************************************** > TimeSpan TimeSpan::operator-(const TimeSpan &other) const Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A reference to a rhs TimeSpan value to subtract from this time span Returns: The result of subtracting other from this Purpose: Overload the operator- function to perform an intersection of two time spans returning the result in a new timespan. ********************************************************************************************/ TimeSpan TimeSpan::operator-(const TimeSpan &other) const { // both bounds must be valid for an intersection if (IsEmpty() || other.IsEmpty()) return (*this); // check for none intersection case TimeSlice lower = other.GetLowerBound(); TimeSlice upper = other.GetUpperBound(); if (upperHI) return (*this); // make an intersection now we know the two actually do intersect if (HIlower) lower=LO; return TimeSpan(lower,upper); } /******************************************************************************************** > TimeSpan& TimeSpan::operator=(const TimeSpan &other) Author: Mike_Kenny (Xara Group Ltd) Created: 17/03/97 Inputs: A reference to another time span Returns: A reference to this time span Purpose: Assignment operator overload, assigns this time span with that of 'other' and returns a reference for further assignment ********************************************************************************************/ TimeSpan& TimeSpan::operator=(const TimeSpan &other) { LO = other.GetLowerBound(); HI = other.GetUpperBound(); return (*this); }