/* * Paper.js - The Swiss Army Knife of Vector Graphics Scripting. * http://paperjs.org/ * * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey * http://lehni.org/ & http://jonathanpuckey.com/ * * Distributed under the MIT license. See LICENSE file for details. * * All rights reserved. */ /** * @name Size * * @class The Size object is used to describe the size of something, through * its {@link #width} and {@link #height} properties. * * @classexample * // Create a size that is 10pt wide and 5pt high * var size = new Size(10, 5); * console.log(size.width); // 10 * console.log(size.height); // 5 */ var Size = this.Size = Base.extend(/** @lends Size# */{ // Tell Base.read that the Point constructor supporst reading with index _readIndex: true, // DOCS: improve Size class description /** * Creates a Size object with the given width and height values. * * @name Size#initialize * @param {Number} width the width * @param {Number} height the height * * @example * // Create a size that is 10pt wide and 5pt high * var size = new Size(10, 5); * console.log(size.width); // 10 * console.log(size.height); // 5 * /** * Creates a Size object using the numbers in the given array as * dimensions. * * @name Size#initialize * @param {array} array * * @example * // Creating a size of width: 320, height: 240 using an array of numbers: * var array = [320, 240]; * var size = new Size(array); * console.log(size.width); // 320 * console.log(size.height); // 240 */ /** * Creates a Size object using the properties in the given object. * * @name Size#initialize * @param {object} object * * @example * // Creating a size of width: 10, height: 20 using an object literal: * * var size = new Size({ * width: 10, * height: 20 * }); * console.log(size.width); // 10 * console.log(size.height); // 20 */ /** * Creates a Size object using the coordinates of the given Size object. * * @name Size#initialize * @param {Size} size */ /** * Creates a Size object using the {@link Point#x} and {@link Point#y} * values of the given Point object. * * @name Size#initialize * @param {Point} point * * @example * var point = new Point(50, 50); * var size = new Size(point); * console.log(size.width); // 50 * console.log(size.height); // 50 */ initialize: function(arg0, arg1) { var type = typeof arg0; if (type === 'number') { var hasHeight = typeof arg1 === 'number'; this.width = arg0; this.height = hasHeight ? arg1 : arg0; if (this._read) this._read = hasHeight ? 2 : 1; } else if (type === 'undefined' || arg0 === null) { this.width = this.height = 0; if (this._read) this._read = arg0 === null ? 1 : 0; } else { if (Array.isArray(arg0)) { this.width = arg0[0]; this.height = arg0.length > 1 ? arg0[1] : arg0[0]; } else if (arg0.width != null) { this.width = arg0.width; this.height = arg0.height; } else if (arg0.x != null) { this.width = arg0.x; this.height = arg0.y; } else { this.width = this.height = 0; if (this._read) this._read = 0; } if (this._read) this._read = 1; } }, /** * @return {String} A string representation of the size. */ toString: function() { var format = Base.formatFloat; return '{ width: ' + format(this.width) + ', height: ' + format(this.height) + ' }'; }, /** * The width of the size * * @name Size#width * @type Number */ /** * The height of the size * * @name Size#height * @type Number */ set: function(width, height) { this.width = width; this.height = height; return this; }, /** * Returns a copy of the size. */ clone: function() { return Size.create(this.width, this.height); }, /** * Returns the addition of the supplied value to the width and height of the * size as a new size. The object itself is not modified! * * @name Size#add * @function * @param {Number} number the number to add * @return {Size} the addition of the size and the value as a new size * * @example * var size = new Size(5, 10); * var result = size + 20; * console.log(result); // {width: 25, height: 30} */ /** * Returns the addition of the width and height of the supplied size to the * size as a new size. The object itself is not modified! * * @name Size#add * @function * @param {Size} size the size to add * @return {Size} the addition of the two sizes as a new size * * @example * var size1 = new Size(5, 10); * var size2 = new Size(10, 20); * var result = size1 + size2; * console.log(result); // {width: 15, height: 30} */ add: function(size) { size = Size.read(arguments); return Size.create(this.width + size.width, this.height + size.height); }, /** * Returns the subtraction of the supplied value from the width and height * of the size as a new size. The object itself is not modified! * The object itself is not modified! * * @name Size#subtract * @function * @param {Number} number the number to subtract * @return {Size} the subtraction of the size and the value as a new size * * @example * var size = new Size(10, 20); * var result = size - 5; * console.log(result); // {width: 5, height: 15} */ /** * Returns the subtraction of the width and height of the supplied size from * the size as a new size. The object itself is not modified! * * @name Size#subtract * @function * @param {Size} size the size to subtract * @return {Size} the subtraction of the two sizes as a new size * * @example * var firstSize = new Size(10, 20); * var secondSize = new Size(5, 5); * var result = firstSize - secondSize; * console.log(result); // {width: 5, height: 15} */ subtract: function(size) { size = Size.read(arguments); return Size.create(this.width - size.width, this.height - size.height); }, /** * Returns the multiplication of the supplied value with the width and * height of the size as a new size. The object itself is not modified! * * @name Size#multiply * @function * @param {Number} number the number to multiply by * @return {Size} the multiplication of the size and the value as a new size * * @example * var size = new Size(10, 20); * var result = size * 2; * console.log(result); // {width: 20, height: 40} */ /** * Returns the multiplication of the width and height of the supplied size * with the size as a new size. The object itself is not modified! * * @name Size#multiply * @function * @param {Size} size the size to multiply by * @return {Size} the multiplication of the two sizes as a new size * * @example * var firstSize = new Size(5, 10); * var secondSize = new Size(4, 2); * var result = firstSize * secondSize; * console.log(result); // {width: 20, height: 20} */ multiply: function(size) { size = Size.read(arguments); return Size.create(this.width * size.width, this.height * size.height); }, /** * Returns the division of the supplied value by the width and height of the * size as a new size. The object itself is not modified! * * @name Size#divide * @function * @param {Number} number the number to divide by * @return {Size} the division of the size and the value as a new size * * @example * var size = new Size(10, 20); * var result = size / 2; * console.log(result); // {width: 5, height: 10} */ /** * Returns the division of the width and height of the supplied size by the * size as a new size. The object itself is not modified! * * @name Size#divide * @function * @param {Size} size the size to divide by * @return {Size} the division of the two sizes as a new size * * @example * var firstSize = new Size(8, 10); * var secondSize = new Size(2, 5); * var result = firstSize / secondSize; * console.log(result); // {width: 4, height: 2} */ divide: function(size) { size = Size.read(arguments); return Size.create(this.width / size.width, this.height / size.height); }, /** * The modulo operator returns the integer remainders of dividing the size * by the supplied value as a new size. * * @name Size#modulo * @function * @param {Number} value * @return {Size} the integer remainders of dividing the size by the value * as a new size * * @example * var size = new Size(12, 6); * console.log(size % 5); // {width: 2, height: 1} */ /** * The modulo operator returns the integer remainders of dividing the size * by the supplied size as a new size. * * @name Size#modulo * @function * @param {Size} size * @return {Size} the integer remainders of dividing the sizes by each * other as a new size * * @example * var size = new Size(12, 6); * console.log(size % new Size(5, 2)); // {width: 2, height: 0} */ modulo: function(size) { size = Size.read(arguments); return Size.create(this.width % size.width, this.height % size.height); }, negate: function() { return Size.create(-this.width, -this.height); }, /** * Checks whether the width and height of the size are equal to those of the * supplied size. * * @param {Size} * @return {Boolean} * * @example * var size = new Size(5, 10); * console.log(size == new Size(5, 10)); // true * console.log(size == new Size(1, 1)); // false * console.log(size != new Size(1, 1)); // true */ equals: function(size) { size = Size.read(arguments); return this.width == size.width && this.height == size.height; }, /** * {@grouptitle Tests} * Checks if this size has both the width and height set to 0. * * @return {Boolean} {@true both width and height are 0} */ isZero: function() { return Numerical.isZero(this.width) && Numerical.isZero(this.height); }, /** * Checks if the width or the height of the size are NaN. * * @return {Boolean} {@true if the width or height of the size are NaN} */ isNaN: function() { return isNaN(this.width) || isNaN(this.height); }, statics: /** @lends Size */{ // See Point.create() create: function(width, height) { return Base.create(Size).set(width, height); }, /** * Returns a new size object with the smallest {@link #width} and * {@link #height} of the supplied sizes. * * @static * @param {Size} size1 * @param {Size} size2 * @returns {Size} The newly created size object * * @example * var size1 = new Size(10, 100); * var size2 = new Size(200, 5); * var minSize = Size.min(size1, size2); * console.log(minSize); // {width: 10, height: 5} */ min: function(size1, size2) { return Size.create( Math.min(size1.width, size2.width), Math.min(size1.height, size2.height)); }, /** * Returns a new size object with the largest {@link #width} and * {@link #height} of the supplied sizes. * * @static * @param {Size} size1 * @param {Size} size2 * @returns {Size} The newly created size object * * @example * var size1 = new Size(10, 100); * var size2 = new Size(200, 5); * var maxSize = Size.max(size1, size2); * console.log(maxSize); // {width: 200, height: 100} */ max: function(size1, size2) { return Size.create( Math.max(size1.width, size2.width), Math.max(size1.height, size2.height)); }, /** * Returns a size object with random {@link #width} and {@link #height} * values between {@code 0} and {@code 1}. * * @returns {Size} The newly created size object * @static * * @example * var maxSize = new Size(100, 100); * var randomSize = Size.random(); * var size = maxSize * randomSize; */ random: function() { return Size.create(Math.random(), Math.random()); } } }, new function() { // Scope for injecting round, ceil, floor, abs: /** * {@grouptitle Math Functions} * * Returns a new size with rounded {@link #width} and {@link #height} values. * The object itself is not modified! * * @name Size#round * @function * @return {Size} * * @example * var size = new Size(10.2, 10.9); * var roundSize = size.round(); * console.log(roundSize); // {x: 10, y: 11} */ /** * Returns a new size with the nearest greater non-fractional values to the * specified {@link #width} and {@link #height} values. The object itself is not * modified! * * @name Size#ceil * @function * @return {Size} * * @example * var size = new Size(10.2, 10.9); * var ceilSize = size.ceil(); * console.log(ceilSize); // {x: 11, y: 11} */ /** * Returns a new size with the nearest smaller non-fractional values to the * specified {@link #width} and {@link #height} values. The object itself is not * modified! * * @name Size#floor * @function * @return {Size} * * @example * var size = new Size(10.2, 10.9); * var floorSize = size.floor(); * console.log(floorSize); // {x: 10, y: 10} */ /** * Returns a new size with the absolute values of the specified {@link #width} * and {@link #height} values. The object itself is not modified! * * @name Size#abs * @function * @return {Size} * * @example * var size = new Size(-5, 10); * var absSize = size.abs(); * console.log(absSize); // {x: 5, y: 10} */ return Base.each(['round', 'ceil', 'floor', 'abs'], function(name) { var op = Math[name]; this[name] = function() { return Size.create(op(this.width), op(this.height)); }; }, {}); }); /** * @name LinkedSize * * @class An internal version of Size that notifies its owner of each change * through setting itself again on the setter that corresponds to the getter * that produced this LinkedSize. See uses of LinkedSize.create() * Note: This prototype is not exported. * * @private */ var LinkedSize = Size.extend({ set: function(width, height, dontNotify) { this._width = width; this._height = height; if (!dontNotify) this._owner[this._setter](this); return this; }, getWidth: function() { return this._width; }, setWidth: function(width) { this._width = width; this._owner[this._setter](this); }, getHeight: function() { return this._height; }, setHeight: function(height) { this._height = height; this._owner[this._setter](this); }, statics: { create: function(owner, setter, width, height, dontLink) { // See LinkedPoint.create() for an explanation about dontLink. if (dontLink) return Size.create(width, height); var size = Base.create(LinkedSize); size._width = width; size._height = height; size._owner = owner; size._setter = setter; return size; } } });