Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / common / Geometry.js
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 WebInspector.Geometry = {};
32
33 /**
34  * @type {number}
35  */
36 WebInspector.Geometry._Eps = 1e-5;
37
38 /**
39  * @constructor
40  * @param {number} x
41  * @param {number} y
42  * @param {number} z
43  */
44 WebInspector.Geometry.Vector = function(x, y, z)
45 {
46     this.x = x;
47     this.y = y;
48     this.z = z;
49 }
50
51 WebInspector.Geometry.Vector.prototype = {
52     /**
53      * @return {number}
54      */
55     length: function()
56     {
57         return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
58     },
59
60     normalize: function()
61     {
62         var length = this.length();
63         if (length <= WebInspector.Geometry._Eps)
64             return;
65
66         this.x /= length;
67         this.y /= length;
68         this.z /= length;
69     }
70 }
71
72 /**
73  * @constructor
74  * @param {number} alpha
75  * @param {number} beta
76  * @param {number} gamma
77  */
78 WebInspector.Geometry.EulerAngles = function(alpha, beta, gamma)
79 {
80     this.alpha = alpha;
81     this.beta = beta;
82     this.gamma = gamma;
83 }
84
85 /**
86  * @param {!CSSMatrix} rotationMatrix
87  * @return {!WebInspector.Geometry.EulerAngles}
88  */
89 WebInspector.Geometry.EulerAngles.fromRotationMatrix = function(rotationMatrix)
90 {
91     var beta = Math.atan2(rotationMatrix.m23, rotationMatrix.m33);
92     var gamma = Math.atan2(-rotationMatrix.m13, Math.sqrt(rotationMatrix.m11 * rotationMatrix.m11 + rotationMatrix.m12 * rotationMatrix.m12));
93     var alpha = Math.atan2(rotationMatrix.m12, rotationMatrix.m11);
94     return new WebInspector.Geometry.EulerAngles(WebInspector.Geometry.radToDeg(alpha), WebInspector.Geometry.radToDeg(beta), WebInspector.Geometry.radToDeg(gamma));
95 }
96
97 /**
98  * @param {!WebInspector.Geometry.Vector} u
99  * @param {!WebInspector.Geometry.Vector} v
100  * @return {number}
101  */
102 WebInspector.Geometry.scalarProduct = function(u, v)
103 {
104     return u.x * v.x + u.y * v.y + u.z * v.z;
105 }
106
107 /**
108  * @param {!WebInspector.Geometry.Vector} u
109  * @param {!WebInspector.Geometry.Vector} v
110  * @return {!WebInspector.Geometry.Vector}
111  */
112 WebInspector.Geometry.crossProduct = function(u, v)
113 {
114     var x = u.y * v.z - u.z * v.y;
115     var y = u.z * v.x - u.x * v.z;
116     var z = u.x * v.y - u.y * v.x;
117     return new WebInspector.Geometry.Vector(x, y, z);
118 }
119
120 /**
121  * @param {!WebInspector.Geometry.Vector} u
122  * @param {!WebInspector.Geometry.Vector} v
123  * @return {!WebInspector.Geometry.Vector}
124  */
125 WebInspector.Geometry.subtract = function(u, v)
126 {
127     var x = u.x - v.x;
128     var y = u.y - v.y;
129     var z = u.z - v.z;
130     return new WebInspector.Geometry.Vector(x, y, z);
131 }
132
133 /**
134  * @param {!WebInspector.Geometry.Vector} v
135  * @param {!CSSMatrix} m
136  * @return {!WebInspector.Geometry.Vector}
137  */
138 WebInspector.Geometry.multiplyVectorByMatrixAndNormalize = function(v, m)
139 {
140     var t = v.x * m.m14 + v.y * m.m24 + v.z * m.m34 + m.m44;
141     var x = (v.x * m.m11 + v.y * m.m21 + v.z * m.m31 + m.m41) / t;
142     var y = (v.x * m.m12 + v.y * m.m22 + v.z * m.m32 + m.m42) / t;
143     var z = (v.x * m.m13 + v.y * m.m23 + v.z * m.m33 + m.m43) / t;
144     return new WebInspector.Geometry.Vector(x, y, z);
145 }
146
147 /**
148  * @param {!WebInspector.Geometry.Vector} u
149  * @param {!WebInspector.Geometry.Vector} v
150  * @return {number}
151  */
152 WebInspector.Geometry.calculateAngle = function(u, v)
153 {
154     var uLength = u.length();
155     var vLength = v.length();
156     if (uLength <= WebInspector.Geometry._Eps || vLength <= WebInspector.Geometry._Eps)
157         return 0;
158     var cos = WebInspector.Geometry.scalarProduct(u, v) / uLength / vLength;
159     if (Math.abs(cos) > 1)
160         return 0;
161     return WebInspector.Geometry.radToDeg(Math.acos(cos));
162 }
163
164 /**
165  * @param {number} rad
166  * @return {number}
167  */
168 WebInspector.Geometry.radToDeg = function(rad)
169 {
170     return rad * 180 / Math.PI;
171 }
172
173 /**
174  * @param {!CSSMatrix} matrix
175  * @param {!Array.<number>} points
176  * @param {{minX: number, maxX: number, minY: number, maxY: number}=} aggregateBounds
177  * @return {!{minX: number, maxX: number, minY: number, maxY: number}}
178  */
179 WebInspector.Geometry.boundsForTransformedPoints = function(matrix, points, aggregateBounds)
180 {
181     if (!aggregateBounds)
182         aggregateBounds = {minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity};
183     if (points.length % 3)
184         console.assert("Invalid size of points array");
185     for (var p = 0; p < points.length; p += 3) {
186         var vector = new WebInspector.Geometry.Vector(points[p], points[p + 1], points[p + 2]);
187         vector = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize(vector, matrix);
188         aggregateBounds.minX = Math.min(aggregateBounds.minX, vector.x);
189         aggregateBounds.maxX = Math.max(aggregateBounds.maxX, vector.x);
190         aggregateBounds.minY = Math.min(aggregateBounds.minY, vector.y);
191         aggregateBounds.maxY = Math.max(aggregateBounds.maxY, vector.y);
192     }
193     return aggregateBounds;
194 }
195
196 /**
197  * @constructor
198  * @param {number} width
199  * @param {number} height
200  */
201 function Size(width, height)
202 {
203     this.width = width;
204     this.height = height;
205 }
206
207 /**
208  * @param {?Size} size
209  * @return {boolean}
210  */
211 Size.prototype.isEqual = function(size)
212 {
213     return !!size && this.width === size.width && this.height === size.height;
214 };
215
216 /**
217  * @param {!Size|number} size
218  * @return {!Size}
219  */
220 Size.prototype.widthToMax = function(size)
221 {
222     return new Size(Math.max(this.width, (typeof size === "number" ? size : size.width)), this.height);
223 };
224
225 /**
226  * @param {!Size|number} size
227  * @return {!Size}
228  */
229 Size.prototype.addWidth = function(size)
230 {
231     return new Size(this.width + (typeof size === "number" ? size : size.width), this.height);
232 };
233
234 /**
235  * @param {!Size|number} size
236  * @return {!Size}
237  */
238 Size.prototype.heightToMax = function(size)
239 {
240     return new Size(this.width, Math.max(this.height, (typeof size === "number" ? size : size.height)));
241 };
242
243 /**
244  * @param {!Size|number} size
245  * @return {!Size}
246  */
247 Size.prototype.addHeight = function(size)
248 {
249     return new Size(this.width, this.height + (typeof size === "number" ? size : size.height));
250 };
251
252
253 /**
254  * @constructor
255  * @param {!Size} minimum
256  * @param {?Size=} preferred
257  */
258 function Constraints(minimum, preferred)
259 {
260     /**
261      * @type {!Size}
262      */
263     this.minimum = minimum;
264
265     /**
266      * @type {!Size}
267      */
268     this.preferred = preferred || minimum;
269
270     if (this.minimum.width > this.preferred.width || this.minimum.height > this.preferred.height)
271         throw new Error("Minimum size is greater than preferred.");
272 }
273
274 /**
275  * @param {?Constraints} constraints
276  * @return {boolean}
277  */
278 Constraints.prototype.isEqual = function(constraints)
279 {
280     return !!constraints && this.minimum.isEqual(constraints.minimum) && this.preferred.isEqual(constraints.preferred);
281 }
282
283 /**
284  * @param {!Constraints|number} value
285  * @return {!Constraints}
286  */
287 Constraints.prototype.widthToMax = function(value)
288 {
289     if (typeof value === "number")
290         return new Constraints(this.minimum.widthToMax(value), this.preferred.widthToMax(value));
291     return new Constraints(this.minimum.widthToMax(value.minimum), this.preferred.widthToMax(value.preferred));
292 }
293
294 /**
295  * @param {!Constraints|number} value
296  * @return {!Constraints}
297  */
298 Constraints.prototype.addWidth = function(value)
299 {
300     if (typeof value === "number")
301         return new Constraints(this.minimum.addWidth(value), this.preferred.addWidth(value));
302     return new Constraints(this.minimum.addWidth(value.minimum), this.preferred.addWidth(value.preferred));
303 }
304
305 /**
306  * @param {!Constraints|number} value
307  * @return {!Constraints}
308  */
309 Constraints.prototype.heightToMax = function(value)
310 {
311     if (typeof value === "number")
312         return new Constraints(this.minimum.heightToMax(value), this.preferred.heightToMax(value));
313     return new Constraints(this.minimum.heightToMax(value.minimum), this.preferred.heightToMax(value.preferred));
314 }
315
316 /**
317  * @param {!Constraints|number} value
318  * @return {!Constraints}
319  */
320 Constraints.prototype.addHeight = function(value)
321 {
322     if (typeof value === "number")
323         return new Constraints(this.minimum.addHeight(value), this.preferred.addHeight(value));
324     return new Constraints(this.minimum.addHeight(value.minimum), this.preferred.addHeight(value.preferred));
325 }