1*ce9c7ef7SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ce9c7ef7SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ce9c7ef7SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ce9c7ef7SAndrew Rist  * distributed with this work for additional information
6*ce9c7ef7SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ce9c7ef7SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ce9c7ef7SAndrew Rist  * "License"); you may not use this file except in compliance
9*ce9c7ef7SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ce9c7ef7SAndrew Rist  *
11*ce9c7ef7SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ce9c7ef7SAndrew Rist  *
13*ce9c7ef7SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ce9c7ef7SAndrew Rist  * software distributed under the License is distributed on an
15*ce9c7ef7SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ce9c7ef7SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ce9c7ef7SAndrew Rist  * specific language governing permissions and limitations
18*ce9c7ef7SAndrew Rist  * under the License.
19*ce9c7ef7SAndrew Rist  *
20*ce9c7ef7SAndrew Rist  *************************************************************/
21*ce9c7ef7SAndrew Rist 
22*ce9c7ef7SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #ifndef _BGFX_RANGE_BASICRANGE_HXX
25cdf0e10cSrcweir #define _BGFX_RANGE_BASICRANGE_HXX
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <sal/types.h>
28cdf0e10cSrcweir #include <float.h>
29cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir 
32cdf0e10cSrcweir namespace basegfx
33cdf0e10cSrcweir {
34cdf0e10cSrcweir 	template< typename T, typename Traits > class BasicRange
35cdf0e10cSrcweir 	{
36cdf0e10cSrcweir 	protected:
37cdf0e10cSrcweir 		T		mnMinimum;
38cdf0e10cSrcweir 		T		mnMaximum;
39cdf0e10cSrcweir 
40cdf0e10cSrcweir 	public:
41cdf0e10cSrcweir         typedef T 		ValueType;
42cdf0e10cSrcweir         typedef Traits	TraitsType;
43cdf0e10cSrcweir 
BasicRange()44cdf0e10cSrcweir         BasicRange() :
45cdf0e10cSrcweir             mnMinimum(Traits::maxVal()),
46cdf0e10cSrcweir 			mnMaximum(Traits::minVal())
47cdf0e10cSrcweir 		{
48cdf0e10cSrcweir 		}
49cdf0e10cSrcweir 
BasicRange(T nValue)50cdf0e10cSrcweir         BasicRange( T nValue ) :
51cdf0e10cSrcweir             mnMinimum(nValue),
52cdf0e10cSrcweir 			mnMaximum(nValue)
53cdf0e10cSrcweir 		{
54cdf0e10cSrcweir 		}
55cdf0e10cSrcweir 
BasicRange(const BasicRange & rRange)56cdf0e10cSrcweir 		BasicRange(const BasicRange& rRange) :
57cdf0e10cSrcweir             mnMinimum(rRange.mnMinimum),
58cdf0e10cSrcweir 			mnMaximum(rRange.mnMaximum)
59cdf0e10cSrcweir 		{
60cdf0e10cSrcweir 		}
61cdf0e10cSrcweir 
reset()62cdf0e10cSrcweir 		void reset()
63cdf0e10cSrcweir 		{
64cdf0e10cSrcweir 			mnMinimum = Traits::maxVal();
65cdf0e10cSrcweir 			mnMaximum = Traits::minVal();
66cdf0e10cSrcweir 		}
67cdf0e10cSrcweir 
isEmpty() const68cdf0e10cSrcweir 		bool isEmpty() const
69cdf0e10cSrcweir 		{
70cdf0e10cSrcweir 			return Traits::maxVal() == mnMinimum;
71cdf0e10cSrcweir 		}
72cdf0e10cSrcweir 
getMinimum() const73cdf0e10cSrcweir         T getMinimum() const { return mnMinimum; }
getMaximum() const74cdf0e10cSrcweir         T getMaximum() const { return mnMaximum; }
75cdf0e10cSrcweir 
getCenter() const76cdf0e10cSrcweir 		double getCenter() const
77cdf0e10cSrcweir 		{
78cdf0e10cSrcweir 			if(isEmpty())
79cdf0e10cSrcweir 			{
80cdf0e10cSrcweir 				return 0.0;
81cdf0e10cSrcweir 			}
82cdf0e10cSrcweir 			else
83cdf0e10cSrcweir 			{
84cdf0e10cSrcweir 				return ((mnMaximum + mnMinimum) / 2.0);
85cdf0e10cSrcweir 			}
86cdf0e10cSrcweir 		}
87cdf0e10cSrcweir 
isInside(T nValue) const88cdf0e10cSrcweir 		bool isInside(T nValue) const
89cdf0e10cSrcweir 		{
90cdf0e10cSrcweir 			if(isEmpty())
91cdf0e10cSrcweir 			{
92cdf0e10cSrcweir 				return false;
93cdf0e10cSrcweir 			}
94cdf0e10cSrcweir 			else
95cdf0e10cSrcweir 			{
96cdf0e10cSrcweir 				return (nValue >= mnMinimum) && (nValue <= mnMaximum);
97cdf0e10cSrcweir 			}
98cdf0e10cSrcweir 		}
99cdf0e10cSrcweir 
isInside(const BasicRange & rRange) const100cdf0e10cSrcweir 		bool isInside(const BasicRange& rRange) const
101cdf0e10cSrcweir 		{
102cdf0e10cSrcweir 			if(isEmpty())
103cdf0e10cSrcweir 			{
104cdf0e10cSrcweir 				return false;
105cdf0e10cSrcweir 			}
106cdf0e10cSrcweir 			else
107cdf0e10cSrcweir 			{
108cdf0e10cSrcweir 				if(rRange.isEmpty())
109cdf0e10cSrcweir 				{
110cdf0e10cSrcweir 					return false;
111cdf0e10cSrcweir 				}
112cdf0e10cSrcweir 				else
113cdf0e10cSrcweir 				{
114cdf0e10cSrcweir 					return (rRange.mnMinimum >= mnMinimum) && (rRange.mnMaximum <= mnMaximum);
115cdf0e10cSrcweir 				}
116cdf0e10cSrcweir 			}
117cdf0e10cSrcweir 		}
118cdf0e10cSrcweir 
overlaps(const BasicRange & rRange) const119cdf0e10cSrcweir 		bool overlaps(const BasicRange& rRange) const
120cdf0e10cSrcweir 		{
121cdf0e10cSrcweir 			if(isEmpty())
122cdf0e10cSrcweir 			{
123cdf0e10cSrcweir 				return false;
124cdf0e10cSrcweir 			}
125cdf0e10cSrcweir 			else
126cdf0e10cSrcweir 			{
127cdf0e10cSrcweir 				if(rRange.isEmpty())
128cdf0e10cSrcweir 				{
129cdf0e10cSrcweir 					return false;
130cdf0e10cSrcweir 				}
131cdf0e10cSrcweir 				else
132cdf0e10cSrcweir 				{
133cdf0e10cSrcweir 					return !((rRange.mnMaximum < mnMinimum) || (rRange.mnMinimum > mnMaximum));
134cdf0e10cSrcweir 				}
135cdf0e10cSrcweir 			}
136cdf0e10cSrcweir 		}
137cdf0e10cSrcweir 
overlapsMore(const BasicRange & rRange) const138cdf0e10cSrcweir 		bool overlapsMore(const BasicRange& rRange) const
139cdf0e10cSrcweir 		{
140cdf0e10cSrcweir 			if(isEmpty() || rRange.isEmpty())
141cdf0e10cSrcweir 				return false;
142cdf0e10cSrcweir 			// returns true if the overlap is more than just a touching at the limits
143cdf0e10cSrcweir 			return ((rRange.mnMaximum > mnMinimum) && (rRange.mnMinimum < mnMaximum));
144cdf0e10cSrcweir 		}
145cdf0e10cSrcweir 
operator ==(const BasicRange & rRange) const146cdf0e10cSrcweir 		bool operator==( const BasicRange& rRange ) const
147cdf0e10cSrcweir 		{
148cdf0e10cSrcweir 			return (mnMinimum == rRange.mnMinimum && mnMaximum == rRange.mnMaximum);
149cdf0e10cSrcweir 		}
150cdf0e10cSrcweir 
operator !=(const BasicRange & rRange) const151cdf0e10cSrcweir 		bool operator!=( const BasicRange& rRange ) const
152cdf0e10cSrcweir 		{
153cdf0e10cSrcweir 			return (mnMinimum != rRange.mnMinimum || mnMaximum != rRange.mnMaximum);
154cdf0e10cSrcweir 		}
155cdf0e10cSrcweir 
operator =(const BasicRange & rRange)156cdf0e10cSrcweir 		BasicRange& operator=(const BasicRange& rRange)
157cdf0e10cSrcweir 		{
158cdf0e10cSrcweir 			mnMinimum = rRange.mnMinimum;
159cdf0e10cSrcweir 			mnMaximum = rRange.mnMaximum;
160cdf0e10cSrcweir 			return *this;
161cdf0e10cSrcweir 		}
162cdf0e10cSrcweir 
equal(const BasicRange & rRange) const163cdf0e10cSrcweir 		bool equal(const BasicRange& rRange) const
164cdf0e10cSrcweir         {
165cdf0e10cSrcweir             return (
166cdf0e10cSrcweir                 fTools::equal(mnMinimum, rRange.mnMinimum) &&
167cdf0e10cSrcweir                 fTools::equal(mnMaximum, rRange.mnMaximum));
168cdf0e10cSrcweir         }
169cdf0e10cSrcweir 
expand(T nValue)170cdf0e10cSrcweir 		void expand(T nValue)
171cdf0e10cSrcweir 		{
172cdf0e10cSrcweir 			if(isEmpty())
173cdf0e10cSrcweir 			{
174cdf0e10cSrcweir 				mnMinimum = mnMaximum = nValue;
175cdf0e10cSrcweir 			}
176cdf0e10cSrcweir 			else
177cdf0e10cSrcweir 			{
178cdf0e10cSrcweir 				if(nValue < mnMinimum)
179cdf0e10cSrcweir 				{
180cdf0e10cSrcweir 					mnMinimum = nValue;
181cdf0e10cSrcweir 				}
182cdf0e10cSrcweir 
183cdf0e10cSrcweir 				if(nValue > mnMaximum)
184cdf0e10cSrcweir 				{
185cdf0e10cSrcweir 					mnMaximum = nValue;
186cdf0e10cSrcweir 				}
187cdf0e10cSrcweir 			}
188cdf0e10cSrcweir 		}
189cdf0e10cSrcweir 
expand(const BasicRange & rRange)190cdf0e10cSrcweir 		void expand(const BasicRange& rRange)
191cdf0e10cSrcweir 		{
192cdf0e10cSrcweir 			if(isEmpty())
193cdf0e10cSrcweir 			{
194cdf0e10cSrcweir 				mnMinimum = rRange.mnMinimum;
195cdf0e10cSrcweir 				mnMaximum = rRange.mnMaximum;
196cdf0e10cSrcweir 			}
197cdf0e10cSrcweir 			else
198cdf0e10cSrcweir 			{
199cdf0e10cSrcweir 				if(!rRange.isEmpty())
200cdf0e10cSrcweir 				{
201cdf0e10cSrcweir 					if(rRange.mnMinimum < mnMinimum)
202cdf0e10cSrcweir 					{
203cdf0e10cSrcweir 						mnMinimum = rRange.mnMinimum;
204cdf0e10cSrcweir 					}
205cdf0e10cSrcweir 
206cdf0e10cSrcweir 					if(rRange.mnMaximum > mnMaximum)
207cdf0e10cSrcweir 					{
208cdf0e10cSrcweir 						mnMaximum = rRange.mnMaximum;
209cdf0e10cSrcweir 					}
210cdf0e10cSrcweir 				}
211cdf0e10cSrcweir 			}
212cdf0e10cSrcweir 		}
213cdf0e10cSrcweir 
intersect(const BasicRange & rRange)214cdf0e10cSrcweir         void intersect(const BasicRange& rRange)
215cdf0e10cSrcweir         {
216cdf0e10cSrcweir 			// here, overlaps also tests all isEmpty() conditions already.
217cdf0e10cSrcweir             if( !overlaps( rRange ) )
218cdf0e10cSrcweir             {
219cdf0e10cSrcweir                 reset();
220cdf0e10cSrcweir             }
221cdf0e10cSrcweir             else
222cdf0e10cSrcweir             {
223cdf0e10cSrcweir 				if(rRange.mnMinimum > mnMinimum)
224cdf0e10cSrcweir 				{
225cdf0e10cSrcweir 					mnMinimum = rRange.mnMinimum;
226cdf0e10cSrcweir 				}
227cdf0e10cSrcweir 
228cdf0e10cSrcweir 				if(rRange.mnMaximum < mnMaximum)
229cdf0e10cSrcweir 				{
230cdf0e10cSrcweir 					mnMaximum = rRange.mnMaximum;
231cdf0e10cSrcweir 				}
232cdf0e10cSrcweir             }
233cdf0e10cSrcweir         }
234cdf0e10cSrcweir 
grow(T nValue)235cdf0e10cSrcweir 		void grow(T nValue)
236cdf0e10cSrcweir 		{
237cdf0e10cSrcweir 			if(!isEmpty())
238cdf0e10cSrcweir 			{
239cdf0e10cSrcweir 				bool bLessThanZero(nValue < 0);
240cdf0e10cSrcweir 
241cdf0e10cSrcweir 				if(nValue > 0 || bLessThanZero)
242cdf0e10cSrcweir 				{
243cdf0e10cSrcweir 					mnMinimum -= nValue;
244cdf0e10cSrcweir 					mnMaximum += nValue;
245cdf0e10cSrcweir 
246cdf0e10cSrcweir 					if(bLessThanZero)
247cdf0e10cSrcweir 					{
248cdf0e10cSrcweir 						// test if range did collapse
249cdf0e10cSrcweir 						if(mnMinimum > mnMaximum)
250cdf0e10cSrcweir 						{
251cdf0e10cSrcweir 							// if yes, collapse to center
252cdf0e10cSrcweir 							mnMinimum = mnMaximum = (mnMinimum + mnMaximum) / 2;
253cdf0e10cSrcweir 						}
254cdf0e10cSrcweir 					}
255cdf0e10cSrcweir 				}
256cdf0e10cSrcweir 			}
257cdf0e10cSrcweir 		}
258cdf0e10cSrcweir 
getRange() const259cdf0e10cSrcweir 		typename Traits::DifferenceType getRange() const
260cdf0e10cSrcweir 		{
261cdf0e10cSrcweir 			if(isEmpty())
262cdf0e10cSrcweir 			{
263cdf0e10cSrcweir 				return Traits::neutral();
264cdf0e10cSrcweir 			}
265cdf0e10cSrcweir 			else
266cdf0e10cSrcweir 			{
267cdf0e10cSrcweir 				return (mnMaximum - mnMinimum);
268cdf0e10cSrcweir 			}
269cdf0e10cSrcweir 		}
270cdf0e10cSrcweir 	};
271cdf0e10cSrcweir 
272cdf0e10cSrcweir     // some pre-fabricated traits
273cdf0e10cSrcweir     struct DoubleTraits
274cdf0e10cSrcweir     {
minValbasegfx::DoubleTraits275cdf0e10cSrcweir         static double minVal() { return DBL_MIN; };
maxValbasegfx::DoubleTraits276cdf0e10cSrcweir         static double maxVal() { return DBL_MAX; };
neutralbasegfx::DoubleTraits277cdf0e10cSrcweir         static double neutral() { return 0.0; };
278cdf0e10cSrcweir 
279cdf0e10cSrcweir         typedef double DifferenceType;
280cdf0e10cSrcweir     };
281cdf0e10cSrcweir 
282cdf0e10cSrcweir     struct Int32Traits
283cdf0e10cSrcweir     {
minValbasegfx::Int32Traits284cdf0e10cSrcweir         static sal_Int32 minVal() { return SAL_MIN_INT32; };
maxValbasegfx::Int32Traits285cdf0e10cSrcweir         static sal_Int32 maxVal() { return SAL_MAX_INT32; };
neutralbasegfx::Int32Traits286cdf0e10cSrcweir         static sal_Int32 neutral() { return 0L; };
287cdf0e10cSrcweir 
288cdf0e10cSrcweir         typedef sal_Int64 DifferenceType;
289cdf0e10cSrcweir     };
290cdf0e10cSrcweir 
291cdf0e10cSrcweir } // end of namespace basegfx
292cdf0e10cSrcweir 
293cdf0e10cSrcweir #endif /* _BGFX_RANGE_BASICRANGE_HXX */
294