License conversion from Flora to Apache 2.0
[platform/core/uifw/dali-core.git] / dali / public-api / math / vector2.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/public-api/math/vector2.h>
20
21 // EXTERNAL INCLUDES
22 #include <math.h>
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/math/vector3.h>
27 #include <dali/public-api/math/math-utils.h>
28 #include <dali/internal/render/common/performance-monitor.h>
29
30 namespace Dali
31 {
32
33 const Vector2 Vector2::ONE(1.0f, 1.0f);
34 const Vector2 Vector2::XAXIS(1.0f, 0.0f);
35 const Vector2 Vector2::YAXIS(0.0f, 1.0f);
36 const Vector2 Vector2::NEGATIVE_XAXIS(-1.0f, 0.0f);
37 const Vector2 Vector2::NEGATIVE_YAXIS(0.0f, -1.0f);
38 const Vector2 Vector2::ZERO(0.0f, 0.0f);
39
40 Vector2::Vector2(const Vector3& vec3)
41 : x(vec3.x),
42   y(vec3.y)
43 {
44 }
45
46 Vector2::Vector2(const Vector4& vec4)
47 : x(vec4.x),
48   y(vec4.y)
49 {
50 }
51
52 Vector2& Vector2::operator=(const Vector3& rhs)
53 {
54   x = rhs.x;
55   y = rhs.y;
56
57   return *this;
58 }
59
60 Vector2& Vector2::operator=(const Vector4& rhs)
61 {
62   x = rhs.x;
63   y = rhs.y;
64
65   return *this;
66 }
67
68
69 bool Vector2::operator==(const Vector2& rhs) const
70 {
71   if (fabsf(x - rhs.x) > GetRangedEpsilon(x, rhs.x))
72   {
73     return false;
74   }
75   if (fabsf(y - rhs.y) > GetRangedEpsilon(y, rhs.y))
76   {
77     return false;
78   }
79
80   return true;
81 }
82
83 float Vector2::Length() const
84 {
85   return sqrtf(LengthSquared());
86 }
87
88 float Vector2::LengthSquared() const
89 {
90   return (x*x) + (y*y);
91 }
92
93 void Vector2::Normalize()
94 {
95   float length = Length();
96   if( ! EqualsZero(length) )
97   {
98     MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,2);
99
100     const float inverseLength = 1.0f / length;
101     x *= inverseLength;
102     y *= inverseLength;
103   }
104 }
105
106 void Vector2::Clamp( const Vector2& min, const Vector2& max )
107 {
108   Dali::ClampInPlace<float>( x, min.x, max.x );
109   Dali::ClampInPlace<float>( y, min.y, max.y );
110 }
111
112 std::ostream& operator<< (std::ostream& o, const Vector2& vector)
113 {
114   return o << "[" << vector.x << ", " << vector.y << "]";
115 }
116
117 Vector2 Clamp( const Vector2& v, const float& min, const float& max )
118 {
119   Vector2 result( v );
120   result.Clamp( Vector2( min, min ) , Vector2( max, max ) );
121
122   return result;
123 }
124
125 Size FitInside( const Size& target, const Size& source )
126 {
127   Size fitted; //zero initialized
128   float widthScale = target.width / source.width;
129   float heightScale = target.height / source.height;
130   if( widthScale < heightScale )
131   {
132     // width scale is smaller so fit according to it
133     fitted.width = source.width * widthScale;
134     fitted.height = source.height * widthScale;
135   }
136   else
137   {
138     // height scale is smaller so fit according to it
139     fitted.width = source.width * heightScale;
140     fitted.height = source.height * heightScale;
141   }
142   return fitted;
143 }
144
145 Size FitScaleToFill( const Size& target, const Size& source )
146 {
147   Size fitted = target;
148   if( target.width > 0.0f && EqualsZero( target.height ) )
149   {
150     float scale = target.width / source.width;
151     fitted.height = scale*source.height;
152   }
153   else if( target.height > 0.0f && EqualsZero( target.width ) )
154   {
155     float scale = target.height / source.height;
156     fitted.width = scale * source.width;
157   }
158   else if( target.height > 0.0f && target.width > 0.0f ) // shouldn't be distorted
159   {
160     float widthScale = source.width / target.width;
161     float heightScale = source.height / target.height;
162     if (widthScale < heightScale && target.width > source.width)
163     {
164       //fit by width
165       fitted.height *= widthScale;
166       fitted.width  *= widthScale;
167     }
168     else if (target.height > source.height)
169     {
170       //fit by height
171       fitted.width  *= heightScale;
172       fitted.height *= heightScale;
173     }
174     // else requested dimensions don't need to be fitted
175   }
176   return fitted;
177 }
178
179 Size ShrinkInside( const Size& target, const Size& source )
180 {
181   // calculate source size vs target size to see if we need to shrink
182   float widthScale = 1.0f;
183   if( target.width < source.width )
184   {
185     // not enough width, width needs to shrink
186     widthScale = target.width / source.width;
187   }
188   float heightScale = 1.0f;
189   if( target.height < source.height )
190   {
191     // not enough height, height needs to shrink
192     heightScale = target.height / source.height;
193   }
194   // use smaller of the scales
195   float scale = std::min( widthScale, heightScale );
196
197   // check if we need to scale
198   if( scale < 1.0f )
199   {
200     // scale natural size to fit inside
201     return source * scale;
202   }
203   // there is enough space so use source size
204   return source;
205 }
206
207 } // namespace Dali