# 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 at6//7//      http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// 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 and13// limitations under the License.1415/**16 * @fileoverview A utility class for representing two-dimensional sizes.17 */181920goog.provide('goog.math.Size');21222324/**25 * Class for representing sizes consisting of a width and height. Undefined26 * width and height support is deprecated and results in compiler warning.27 * @param {number} width Width.28 * @param {number} height Height.29 * @constructor30 */31goog.math.Size = function(width, height) {32  /**33   * Width34   * @type {number}35   */36  this.width = width;3738  /**39   * Height40   * @type {number}41   */42  this.height = height;43};444546/**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 equal51 *     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};626364/**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};707172if (goog.DEBUG) {73  /**74   * Returns a nice string representing size.75   * @return {string} In the form (50 x 73).76   * @override77   */78  goog.math.Size.prototype.toString = function() {79    return '(' + this.width + ' x ' + this.height + ')';80  };81}828384/**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};909192/**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};9899100/**101 * @return {number} The area of the size (width * height).102 */103goog.math.Size.prototype.area = function() {104  return this.width * this.height;105};106107108/**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};114115116/**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};122123124/**125 * @return {boolean} True if the size has zero area, false if both dimensions126 *     are non-zero numbers.127 */128goog.math.Size.prototype.isEmpty = function() {129  return !this.area();130};131132133/**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};142143144/**145 * @param {!goog.math.Size} target The target size.146 * @return {boolean} True if this Size is the same size or smaller than the147 *     target size in both dimensions.148 */149goog.math.Size.prototype.fitsInside = function(target) {150  return this.width <= target.width && this.height <= target.height;151};152153154/**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};163164165/**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};174175176/**177 * Scales this size by the given scale factors. The width and height are scaled178 * by {@code sx} and {@code opt_sy} respectively.  If {@code opt_sy} is not179 * 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};190191192/**193 * Uniformly scales the size to fit inside the dimensions of a given size. The194 * 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;204205  return this.scale(s);206};