# 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 | * @author brenneman@google.com (Shawn Brenneman)
18 | */
19 |
20 |
21 | goog.provide('goog.math.Size');
22 |
23 |
24 |
25 | /**
26 | * Class for representing sizes consisting of a width and height. Undefined
27 | * width and height support is deprecated and results in compiler warning.
28 | * @param {number} width Width.
29 | * @param {number} height Height.
30 | * @struct
31 | * @constructor
32 | */
33 | goog.math.Size = function(width, height) {
34 | /**
35 | * Width
36 | * @type {number}
37 | */
38 | this.width = width;
39 |
40 | /**
41 | * Height
42 | * @type {number}
43 | */
44 | this.height = height;
45 | };
46 |
47 |
48 | /**
49 | * Compares sizes for equality.
50 | * @param {goog.math.Size} a A Size.
51 | * @param {goog.math.Size} b A Size.
52 | * @return {boolean} True iff the sizes have equal widths and equal
53 | * heights, or if both are null.
54 | */
55 | goog.math.Size.equals = function(a, b) {
56 | if (a == b) {
57 | return true;
58 | }
59 | if (!a || !b) {
60 | return false;
61 | }
62 | return a.width == b.width && a.height == b.height;
63 | };
64 |
65 |
66 | /**
67 | * @return {!goog.math.Size} A new copy of the Size.
68 | */
69 | goog.math.Size.prototype.clone = function() {
70 | return new goog.math.Size(this.width, this.height);
71 | };
72 |
73 |
74 | if (goog.DEBUG) {
75 | /**
76 | * Returns a nice string representing size.
77 | * @return {string} In the form (50 x 73).
78 | * @override
79 | */
80 | goog.math.Size.prototype.toString = function() {
81 | return '(' + this.width + ' x ' + this.height + ')';
82 | };
83 | }
84 |
85 |
86 | /**
87 | * @return {number} The longer of the two dimensions in the size.
88 | */
89 | goog.math.Size.prototype.getLongest = function() {
90 | return Math.max(this.width, this.height);
91 | };
92 |
93 |
94 | /**
95 | * @return {number} The shorter of the two dimensions in the size.
96 | */
97 | goog.math.Size.prototype.getShortest = function() {
98 | return Math.min(this.width, this.height);
99 | };
100 |
101 |
102 | /**
103 | * @return {number} The area of the size (width * height).
104 | */
105 | goog.math.Size.prototype.area = function() {
106 | return this.width * this.height;
107 | };
108 |
109 |
110 | /**
111 | * @return {number} The perimeter of the size (width + height) * 2.
112 | */
113 | goog.math.Size.prototype.perimeter = function() {
114 | return (this.width + this.height) * 2;
115 | };
116 |
117 |
118 | /**
119 | * @return {number} The ratio of the size's width to its height.
120 | */
121 | goog.math.Size.prototype.aspectRatio = function() {
122 | return this.width / this.height;
123 | };
124 |
125 |
126 | /**
127 | * @return {boolean} True if the size has zero area, false if both dimensions
128 | * are non-zero numbers.
129 | */
130 | goog.math.Size.prototype.isEmpty = function() {
131 | return !this.area();
132 | };
133 |
134 |
135 | /**
136 | * Clamps the width and height parameters upward to integer values.
137 | * @return {!goog.math.Size} This size with ceil'd components.
138 | */
139 | goog.math.Size.prototype.ceil = function() {
140 | this.width = Math.ceil(this.width);
141 | this.height = Math.ceil(this.height);
142 | return this;
143 | };
144 |
145 |
146 | /**
147 | * @param {!goog.math.Size} target The target size.
148 | * @return {boolean} True if this Size is the same size or smaller than the
149 | * target size in both dimensions.
150 | */
151 | goog.math.Size.prototype.fitsInside = function(target) {
152 | return this.width <= target.width && this.height <= target.height;
153 | };
154 |
155 |
156 | /**
157 | * Clamps the width and height parameters downward to integer values.
158 | * @return {!goog.math.Size} This size with floored components.
159 | */
160 | goog.math.Size.prototype.floor = function() {
161 | this.width = Math.floor(this.width);
162 | this.height = Math.floor(this.height);
163 | return this;
164 | };
165 |
166 |
167 | /**
168 | * Rounds the width and height parameters to integer values.
169 | * @return {!goog.math.Size} This size with rounded components.
170 | */
171 | goog.math.Size.prototype.round = function() {
172 | this.width = Math.round(this.width);
173 | this.height = Math.round(this.height);
174 | return this;
175 | };
176 |
177 |
178 | /**
179 | * Scales this size by the given scale factors. The width and height are scaled
180 | * by {@code sx} and {@code opt_sy} respectively. If {@code opt_sy} is not
181 | * given, then {@code sx} is used for both the width and height.
182 | * @param {number} sx The scale factor to use for the width.
183 | * @param {number=} opt_sy The scale factor to use for the height.
184 | * @return {!goog.math.Size} This Size object after scaling.
185 | */
186 | goog.math.Size.prototype.scale = function(sx, opt_sy) {
187 | var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
188 | this.width *= sx;
189 | this.height *= sy;
190 | return this;
191 | };
192 |
193 |
194 | /**
195 | * Uniformly scales the size to perfectly cover the dimensions of a given size.
196 | * If the size is already larger than the target, it will be scaled down to the
197 | * minimum size at which it still covers the entire target. The original aspect
198 | * ratio will be preserved.
199 | *
200 | * This function assumes that both Sizes contain strictly positive dimensions.
201 | * @param {!goog.math.Size} target The target size.
202 | * @return {!goog.math.Size} This Size object, after optional scaling.
203 | */
204 | goog.math.Size.prototype.scaleToCover = function(target) {
205 | var s = this.aspectRatio() <= target.aspectRatio() ?
206 | target.width / this.width :
207 | target.height / this.height;
208 |
209 | return this.scale(s);
210 | };
211 |
212 |
213 | /**
214 | * Uniformly scales the size to fit inside the dimensions of a given size. The
215 | * original aspect ratio will be preserved.
216 | *
217 | * This function assumes that both Sizes contain strictly positive dimensions.
218 | * @param {!goog.math.Size} target The target size.
219 | * @return {!goog.math.Size} This Size object, after optional scaling.
220 | */
221 | goog.math.Size.prototype.scaleToFit = function(target) {
222 | var s = this.aspectRatio() > target.aspectRatio() ?
223 | target.width / this.width :
224 | target.height / this.height;
225 |
226 | return this.scale(s);
227 | };