lib/goog/math/size.js

1// Copyright 2007 The Closure Library Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS-IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/**
16 * @fileoverview A utility class for representing two-dimensional sizes.
17 */
18
19
20goog.provide('goog.math.Size');
21
22
23
24/**
25 * Class for representing sizes consisting of a width and height. Undefined
26 * width and height support is deprecated and results in compiler warning.
27 * @param {number} width Width.
28 * @param {number} height Height.
29 * @constructor
30 */
31goog.math.Size = function(width, height) {
32 /**
33 * Width
34 * @type {number}
35 */
36 this.width = width;
37
38 /**
39 * Height
40 * @type {number}
41 */
42 this.height = height;
43};
44
45
46/**
47 * Compares sizes for equality.
48 * @param {goog.math.Size} a A Size.
49 * @param {goog.math.Size} b A Size.
50 * @return {boolean} True iff the sizes have equal widths and equal
51 * heights, or if both are null.
52 */
53goog.math.Size.equals = function(a, b) {
54 if (a == b) {
55 return true;
56 }
57 if (!a || !b) {
58 return false;
59 }
60 return a.width == b.width && a.height == b.height;
61};
62
63
64/**
65 * @return {!goog.math.Size} A new copy of the Size.
66 */
67goog.math.Size.prototype.clone = function() {
68 return new goog.math.Size(this.width, this.height);
69};
70
71
72if (goog.DEBUG) {
73 /**
74 * Returns a nice string representing size.
75 * @return {string} In the form (50 x 73).
76 * @override
77 */
78 goog.math.Size.prototype.toString = function() {
79 return '(' + this.width + ' x ' + this.height + ')';
80 };
81}
82
83
84/**
85 * @return {number} The longer of the two dimensions in the size.
86 */
87goog.math.Size.prototype.getLongest = function() {
88 return Math.max(this.width, this.height);
89};
90
91
92/**
93 * @return {number} The shorter of the two dimensions in the size.
94 */
95goog.math.Size.prototype.getShortest = function() {
96 return Math.min(this.width, this.height);
97};
98
99
100/**
101 * @return {number} The area of the size (width * height).
102 */
103goog.math.Size.prototype.area = function() {
104 return this.width * this.height;
105};
106
107
108/**
109 * @return {number} The perimeter of the size (width + height) * 2.
110 */
111goog.math.Size.prototype.perimeter = function() {
112 return (this.width + this.height) * 2;
113};
114
115
116/**
117 * @return {number} The ratio of the size's width to its height.
118 */
119goog.math.Size.prototype.aspectRatio = function() {
120 return this.width / this.height;
121};
122
123
124/**
125 * @return {boolean} True if the size has zero area, false if both dimensions
126 * are non-zero numbers.
127 */
128goog.math.Size.prototype.isEmpty = function() {
129 return !this.area();
130};
131
132
133/**
134 * Clamps the width and height parameters upward to integer values.
135 * @return {!goog.math.Size} This size with ceil'd components.
136 */
137goog.math.Size.prototype.ceil = function() {
138 this.width = Math.ceil(this.width);
139 this.height = Math.ceil(this.height);
140 return this;
141};
142
143
144/**
145 * @param {!goog.math.Size} target The target size.
146 * @return {boolean} True if this Size is the same size or smaller than the
147 * target size in both dimensions.
148 */
149goog.math.Size.prototype.fitsInside = function(target) {
150 return this.width <= target.width && this.height <= target.height;
151};
152
153
154/**
155 * Clamps the width and height parameters downward to integer values.
156 * @return {!goog.math.Size} This size with floored components.
157 */
158goog.math.Size.prototype.floor = function() {
159 this.width = Math.floor(this.width);
160 this.height = Math.floor(this.height);
161 return this;
162};
163
164
165/**
166 * Rounds the width and height parameters to integer values.
167 * @return {!goog.math.Size} This size with rounded components.
168 */
169goog.math.Size.prototype.round = function() {
170 this.width = Math.round(this.width);
171 this.height = Math.round(this.height);
172 return this;
173};
174
175
176/**
177 * Scales this size by the given scale factors. The width and height are scaled
178 * by {@code sx} and {@code opt_sy} respectively. If {@code opt_sy} is not
179 * given, then {@code sx} is used for both the width and height.
180 * @param {number} sx The scale factor to use for the width.
181 * @param {number=} opt_sy The scale factor to use for the height.
182 * @return {!goog.math.Size} This Size object after scaling.
183 */
184goog.math.Size.prototype.scale = function(sx, opt_sy) {
185 var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
186 this.width *= sx;
187 this.height *= sy;
188 return this;
189};
190
191
192/**
193 * Uniformly scales the size to fit inside the dimensions of a given size. The
194 * original aspect ratio will be preserved.
195 *
196 * This function assumes that both Sizes contain strictly positive dimensions.
197 * @param {!goog.math.Size} target The target size.
198 * @return {!goog.math.Size} This Size object, after optional scaling.
199 */
200goog.math.Size.prototype.scaleToFit = function(target) {
201 var s = this.aspectRatio() > target.aspectRatio() ?
202 target.width / this.width :
203 target.height / this.height;
204
205 return this.scale(s);
206};