(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.p5 = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) {
self._completeHandlers.shift()(resp)
}
}
function success (resp) {
var type = o['type'] || resp && setType(resp.getResponseHeader('Content-Type')) // resp can be undefined in IE
resp = (type !== 'jsonp') ? self.request : resp
// use global data filter on response text
var filteredResponse = globalSetupOptions.dataFilter(resp.responseText, type)
, r = filteredResponse
try {
resp.responseText = r
} catch (e) {
// can't assign this in IE<=8, just ignore
}
if (r) {
switch (type) {
case 'json':
try {
resp = win.JSON ? win.JSON.parse(r) : eval('(' + r + ')')
} catch (err) {
return error(resp, 'Could not parse JSON in response', err)
}
break
case 'js':
resp = eval(r)
break
case 'html':
resp = r
break
case 'xml':
resp = resp.responseXML
&& resp.responseXML.parseError // IE trololo
&& resp.responseXML.parseError.errorCode
&& resp.responseXML.parseError.reason
? null
: resp.responseXML
break
}
}
self._responseArgs.resp = resp
self._fulfilled = true
fn(resp)
self._successHandler(resp)
while (self._fulfillmentHandlers.length > 0) {
resp = self._fulfillmentHandlers.shift()(resp)
}
complete(resp)
}
function timedOut() {
self._timedOut = true
self.request.abort()
}
function error(resp, msg, t) {
resp = self.request
self._responseArgs.resp = resp
self._responseArgs.msg = msg
self._responseArgs.t = t
self._erred = true
while (self._errorHandlers.length > 0) {
self._errorHandlers.shift()(resp, msg, t)
}
complete(resp)
}
this.request = getRequest.call(this, success, error)
}
Reqwest.prototype = {
abort: function () {
this._aborted = true
this.request.abort()
}
, retry: function () {
init.call(this, this.o, this.fn)
}
/**
* Small deviation from the Promises A CommonJs specification
* http://wiki.commonjs.org/wiki/Promises/A
*/
/**
* `then` will execute upon successful requests
*/
, then: function (success, fail) {
success = success || function () {}
fail = fail || function () {}
if (this._fulfilled) {
this._responseArgs.resp = success(this._responseArgs.resp)
} else if (this._erred) {
fail(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
} else {
this._fulfillmentHandlers.push(success)
this._errorHandlers.push(fail)
}
return this
}
/**
* `always` will execute whether the request succeeds or fails
*/
, always: function (fn) {
if (this._fulfilled || this._erred) {
fn(this._responseArgs.resp)
} else {
this._completeHandlers.push(fn)
}
return this
}
/**
* `fail` will execute when the request fails
*/
, fail: function (fn) {
if (this._erred) {
fn(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
} else {
this._errorHandlers.push(fn)
}
return this
}
, 'catch': function (fn) {
return this.fail(fn)
}
}
function reqwest(o, fn) {
return new Reqwest(o, fn)
}
// normalize newline variants according to spec -> CRLF
function normalize(s) {
return s ? s.replace(/\r?\n/g, '\r\n') : ''
}
function serial(el, cb) {
var n = el.name
, t = el.tagName.toLowerCase()
, optCb = function (o) {
// IE gives value="" even where there is no value attribute
// 'specified' ref: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-862529273
if (o && !o['disabled'])
cb(n, normalize(o['attributes']['value'] && o['attributes']['value']['specified'] ? o['value'] : o['text']))
}
, ch, ra, val, i
// don't serialize elements that are disabled or without a name
if (el.disabled || !n) return
switch (t) {
case 'input':
if (!/reset|button|image|file/i.test(el.type)) {
ch = /checkbox/i.test(el.type)
ra = /radio/i.test(el.type)
val = el.value
// WebKit gives us "" instead of "on" if a checkbox has no value, so correct it here
;(!(ch || ra) || el.checked) && cb(n, normalize(ch && val === '' ? 'on' : val))
}
break
case 'textarea':
cb(n, normalize(el.value))
break
case 'select':
if (el.type.toLowerCase() === 'select-one') {
optCb(el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null)
} else {
for (i = 0; el.length && i < el.length; i++) {
el.options[i].selected && optCb(el.options[i])
}
}
break
}
}
// collect up all form elements found from the passed argument elements all
// the way down to child elements; pass a '
*
* When passing in multiple options, pass them in as separate parameters,
* seperated by commas. For example:
*
*
* loadTable("my_csv_file.csv", "csv", "header")
*
*
*
* All files loaded and saved use UTF-8 encoding.
*
* This method is asynchronous, meaning it may not finish before the next
* line in your sketch is executed. Calling loadTable() inside preload()
* guarantees to complete the operation before setup() and draw() are called.
* Outside preload(), you may supply a callback function to handle the object.
*
*
* @method loadTable
* @param {String} filename name of the file or URL to load
* @param {String|Strings} [options] "header" "csv" "tsv"
* @param {Function} [callback] function to be executed after
* loadTable() completes, Table object is
* passed in as first argument
* @return {Object} Table object containing data
*
* @example
*
*
* // Given the following CSV file called "mammals.csv"
* // located in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* //the file can be remote
* //table = loadTable("http://p5js.org/reference/assets/mammals.csv",
* // "csv", "header");
* }
*
* function setup() {
* //count the columns
* print(table.getRowCount() + " total rows in table");
* print(table.getColumnCount() + " total columns in table");
*
* print(table.getColumn("name"));
* //["Goat", "Leopard", "Zebra"]
*
* //cycle through the table
* for (var r = 0; r < table.getRowCount(); r++)
* for (var c = 0; c < table.getColumnCount(); c++) {
* print(table.getString(r, c));
* }
* }
*
*
*/
p5.prototype.loadTable = function (path) {
var callback = null;
var options = [];
var header = false;
var sep = ',';
var separatorSet = false;
for (var i = 1; i < arguments.length; i++) {
if (typeof(arguments[i]) === 'function' ){
callback = arguments[i];
}
else if (typeof(arguments[i]) === 'string') {
options.push(arguments[i]);
if (arguments[i] === 'header') {
header = true;
}
if (arguments[i] === 'csv') {
if (separatorSet) {
throw new Error('Cannot set multiple separator types.');
}
else {
sep = ',';
separatorSet = true;
}
}
else if (arguments[i] === 'tsv') {
if (separatorSet) {
throw new Error('Cannot set multiple separator types.');
}
else {
sep = '\t';
separatorSet = true;
}
}
}
}
var t = new p5.Table();
reqwest({url: path, crossOrigin: true, type: 'csv'})
.then(function(resp) {
resp = resp.responseText;
var state = {};
// define constants
var PRE_TOKEN = 0,
MID_TOKEN = 1,
POST_TOKEN = 2,
POST_RECORD = 4;
var QUOTE = '\"',
CR = '\r',
LF = '\n';
var records = [];
var offset = 0;
var currentRecord = null;
var currentChar;
var recordBegin = function () {
state.escaped = false;
currentRecord = [];
tokenBegin();
};
var recordEnd = function () {
state.currentState = POST_RECORD;
records.push(currentRecord);
currentRecord = null;
};
var tokenBegin = function() {
state.currentState = PRE_TOKEN;
state.token = '';
};
var tokenEnd = function() {
currentRecord.push(state.token);
tokenBegin();
};
while(true) {
currentChar = resp[offset++];
// EOF
if(currentChar == null) {
if (state.escaped) {
throw new Error('Unclosed quote in file.');
}
if (currentRecord){
tokenEnd();
recordEnd();
break;
}
}
if(currentRecord === null) {
recordBegin();
}
// Handle opening quote
if (state.currentState === PRE_TOKEN) {
if (currentChar === QUOTE) {
state.escaped = true;
state.currentState = MID_TOKEN;
continue;
}
state.currentState = MID_TOKEN;
}
// mid-token and escaped, look for sequences and end quote
if (state.currentState === MID_TOKEN && state.escaped) {
if (currentChar === QUOTE) {
if (resp[offset] === QUOTE) {
state.token += QUOTE;
offset++;
}
else {
state.escaped = false;
state.currentState = POST_TOKEN;
}
}
else {
state.token += currentChar;
}
continue;
}
// fall-through: mid-token or post-token, not escaped
if (currentChar === CR ) {
if( resp[offset] === LF ) {
offset++;
}
tokenEnd();
recordEnd();
}
else if (currentChar === LF) {
tokenEnd();
recordEnd();
}
else if (currentChar === sep) {
tokenEnd();
}
else if( state.currentState === MID_TOKEN ){
state.token += currentChar;
}
}
// set up column names
if (header) {
t.columns = records.shift();
}
else {
for (i = 0; i < records.length; i++){
t.columns[i] = i.toString();
}
}
var row;
for (i =0; i saveJSON, saveStrings, saveTable
// filename, [extension] [canvas] --> saveImage
/**
* Save an image, text, json, csv, wav, or html. Prompts download to
* the client's computer. Note that it is not recommended to call save()
* within draw if it's looping, as the save() function will open a new save
* dialog every frame.
* The default behavior is to save the canvas as an image. You can
* optionally specify a filename.
* For example:
*
* save();
* save('myCanvas.jpg'); // save a specific canvas with a filename
*
*
* Alternately, the first parameter can be a pointer to a canvas
* p5.Element, an Array of Strings,
* an Array of JSON, a JSON object, a p5.Table, a p5.Image, or a
* p5.SoundFile (requires p5.sound). The second parameter is a filename
* (including extension). The third parameter is for options specific
* to this type of object. This method will save a file that fits the
* given paramaters. For example:
*
*
*
* save('myCanvas.jpg'); // Saves canvas as an image
*
* var cnv = createCanvas(100, 100);
* save(cnv, 'myCanvas.jpg'); // Saves canvas as an image
*
* var gb = createGraphics(100, 100);
* save(gb, 'myGraphics.jpg'); // Saves p5.Renderer object as an image
*
* save(myTable, 'myTable.html'); // Saves table as html file
* save(myTable, 'myTable.csv',); // Comma Separated Values
* save(myTable, 'myTable.tsv'); // Tab Separated Values
*
* save(myJSON, 'my.json'); // Saves pretty JSON
* save(myJSON, 'my.json', true); // Optimizes JSON filesize
*
* save(img, 'my.png'); // Saves pImage as a png image
*
* save(arrayOfStrings, 'my.txt'); // Saves strings to a text file with line
* // breaks after each item in the array
*
*
* @method save
* @param {[Object|String]} objectOrFilename If filename is provided, will
* save canvas as an image with
* either png or jpg extension
* depending on the filename.
* If object is provided, will
* save depending on the object
* and filename (see examples
* above).
* @param {[String]} filename If an object is provided as the first
* parameter, then the second parameter
* indicates the filename,
* and should include an appropriate
* file extension (see examples above).
* @param {[Boolean/String]} options Additional options depend on
* filetype. For example, when saving JSON,
* true
indicates that the
* output will be optimized for filesize,
* rather than readability.
*/
p5.prototype.save = function(object, _filename, _options) {
// parse the arguments and figure out which things we are saving
var args = arguments;
// =================================================
// OPTION 1: saveCanvas...
// if no arguments are provided, save canvas
var cnv = this._curElement.elt;
if (args.length === 0) {
p5.prototype.saveCanvas(cnv);
return;
}
// otherwise, parse the arguments
// if first param is a p5Graphics, then saveCanvas
else if (args[0] instanceof p5.Renderer) {
p5.prototype.saveCanvas(args[0].elt, args[1], args[2]);
return;
}
// if 1st param is String and only one arg, assume it is canvas filename
else if (args.length === 1 && typeof(args[0]) === 'string') {
p5.prototype.saveCanvas(cnv, args[0]);
}
// =================================================
// OPTION 2: extension clarifies saveStrings vs. saveJSON
else {
var extension = _checkFileExtension(args[1], args[2])[1];
switch(extension){
case 'json':
p5.prototype.saveJSON(args[0], args[1], args[2]);
return;
case 'txt':
p5.prototype.saveStrings(args[0], args[1], args[2]);
return;
// =================================================
// OPTION 3: decide based on object...
default:
if (args[0] instanceof Array) {
p5.prototype.saveStrings(args[0], args[1], args[2]);
}
else if (args[0] instanceof p5.Table) {
p5.prototype.saveTable(args[0], args[1], args[2], args[3]);
}
else if (args[0] instanceof p5.Image) {
p5.prototype.saveCanvas(args[0].canvas, args[1]);
}
else if (args[0] instanceof p5.SoundFile) {
p5.prototype.saveSound(args[0], args[1], args[2], args[3]);
}
}
}
};
/**
* Writes the contents of an Array or a JSON object to a .json file.
* The file saving process and location of the saved file will
* vary between web browsers.
*
* @method saveJSON
* @param {Array|Object} json
* @param {String} filename
* @param {Boolean} [optimize] If true, removes line breaks
* and spaces from the output
* file to optimize filesize
* (but not readability).
* @example
*
* var json;
*
* function setup() {
*
* json = {}; // new JSON Object
*
* json.id = 0;
* json.species = 'Panthera leo';
* json.name = 'Lion';
*
* // To save, un-comment the line below, then click 'run'
* // saveJSONObject(json, 'lion.json');
* }
*
* // Saves the following to a file called "lion.json":
* // {
* // "id": 0,
* // "species": "Panthera leo",
* // "name": "Lion"
* // }
*
*/
p5.prototype.saveJSON = function(json, filename, opt) {
var stringify;
if (opt){
stringify = JSON.stringify( json );
} else {
stringify = JSON.stringify( json, undefined, 2);
}
console.log(stringify);
this.saveStrings(stringify.split('\n'), filename, 'json');
};
p5.prototype.saveJSONObject = p5.prototype.saveJSON;
p5.prototype.saveJSONArray = p5.prototype.saveJSON;
p5.prototype.saveStream = function() {
// TODO
throw 'not yet implemented';
};
/**
* Writes an array of Strings to a text file, one line per String.
* The file saving process and location of the saved file will
* vary between web browsers.
*
* @method saveStrings
* @param {Array} list string array to be written
* @param {String} filename filename for output
* @example
*
* var words = 'apple bear cat dog';
*
* // .split() outputs an Array
* var list = split(words, ' ');
*
* // To save the file, un-comment next line and click 'run'
* // saveStrings(list, 'nouns.txt');
*
* // Saves the following to a file called 'nouns.txt':
* //
* // apple
* // bear
* // cat
* // dog
*
*/
p5.prototype.saveStrings = function(list, filename, extension) {
var ext = extension || 'txt';
var pWriter = this.createWriter(filename, ext);
for (var i in list) {
if (i < list.length - 1) {
pWriter.println(list[i]);
} else {
pWriter.print(list[i]);
}
}
pWriter.close();
pWriter.flush();
};
p5.prototype.saveXML = function() {
// TODO
throw 'not yet implemented';
};
p5.prototype.selectOutput = function() {
// TODO
throw 'not yet implemented';
};
// =======
// HELPERS
// =======
function escapeHelper(content) {
return content
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
/**
* Writes the contents of a Table object to a file. Defaults to a
* text file with comma-separated-values ('csv') but can also
* use tab separation ('tsv'), or generate an HTML table ('html').
* The file saving process and location of the saved file will
* vary between web browsers.
*
* @method saveTable
* @param {p5.Table} Table the Table object to save to a file
* @param {String} filename the filename to which the Table should be saved
* @param {[String]} options can be one of "tsv", "csv", or "html"
* @example
*
* var table;
*
* function setup() {
* table = new p5.Table();
*
* table.addColumn('id');
* table.addColumn('species');
* table.addColumn('name');
*
* var newRow = table.addRow();
* newRow.setNum('id', table.getRowCount() - 1);
* newRow.setString('species', 'Panthera leo');
* newRow.setString('name', 'Lion');
*
* // To save, un-comment next line then click 'run'
* // saveTable(table, 'new.csv');
* }
*
* // Saves the following to a file called 'new.csv':
* // id,species,name
* // 0,Panthera leo,Lion
*
*/
p5.prototype.saveTable = function(table, filename, options) {
var pWriter = this.createWriter(filename, options);
var header = table.columns;
var sep = ','; // default to CSV
if (options === 'tsv') {
sep = '\t';
}
if (options !== 'html') {
// make header if it has values
if (header[0] !== '0') {
for (var h = 0; h < header.length; h++ ) {
if (h < header.length - 1){
pWriter.print(header[h] + sep);
} else {
pWriter.println(header[h]);
}
}
}
// make rows
for (var i = 0; i < table.rows.length; i++ ) {
var j;
for (j = 0; j < table.rows[i].arr.length; j++) {
if (j < table.rows[i].arr.length - 1) {
pWriter.print(table.rows[i].arr[j] + sep);
}
else if (i < table.rows.length - 1) {
pWriter.println(table.rows[i].arr[j]);
} else {
pWriter.print(table.rows[i].arr[j]); // no line break
}
}
}
}
// otherwise, make HTML
else {
pWriter.println('');
pWriter.println('');
var str = ' ';
pWriter.println(str);
pWriter.println('');
pWriter.println('');
pWriter.println(' ');
// make header if it has values
if (header[0] !== '0') {
pWriter.println(' ');
for (var k = 0; k < header.length; k++ ) {
var e = escapeHelper(header[k]);
pWriter.println(' ' +e);
pWriter.println(' | ');
}
pWriter.println('
');
}
// make rows
for (var row = 0; row < table.rows.length; row++) {
pWriter.println(' ');
for (var col = 0; col < table.columns.length; col++) {
var entry = table.rows[row].getString(col);
var htmlEntry = escapeHelper(entry);
pWriter.println(' ' +htmlEntry);
pWriter.println(' | ');
}
pWriter.println('
');
}
pWriter.println('
');
pWriter.println('');
pWriter.print('');
}
// close and flush the pWriter
pWriter.close();
pWriter.flush();
}; // end saveTable()
/**
* Generate a blob of file data as a url to prepare for download.
* Accepts an array of data, a filename, and an extension (optional).
* This is a private function because it does not do any formatting,
* but it is used by saveStrings, saveJSON, saveTable etc.
*
* @param {Array} dataToDownload
* @param {String} filename
* @param {[String]} extension
* @private
*/
p5.prototype.writeFile = function(dataToDownload, filename, extension) {
var type = 'application\/octet-stream';
if (p5.prototype._isSafari() ) {
type = 'text\/plain';
}
var blob = new Blob(dataToDownload, {'type': type});
var href = window.URL.createObjectURL(blob);
p5.prototype.downloadFile(href, filename, extension);
};
/**
* Forces download. Accepts a url to filedata/blob, a filename,
* and an extension (optional).
* This is a private function because it does not do any formatting,
* but it is used by saveStrings, saveJSON, saveTable etc.
*
* @param {String} href i.e. an href generated by createObjectURL
* @param {[String]} filename
* @param {[String]} extension
*/
p5.prototype.downloadFile = function(href, fName, extension) {
var fx = _checkFileExtension(fName, extension);
var filename = fx[0];
var ext = fx[1];
var a = document.createElement('a');
a.href = href;
a.download = filename;
// Firefox requires the link to be added to the DOM before click()
a.onclick = destroyClickedElement;
a.style.display = 'none';
document.body.appendChild(a);
// Safari will open this file in the same page as a confusing Blob.
if (p5.prototype._isSafari() ) {
var aText = 'Hello, Safari user! To download this file...\n';
aText += '1. Go to File --> Save As.\n';
aText += '2. Choose "Page Source" as the Format.\n';
aText += '3. Name it with this extension: .\"' + ext+'\"';
alert(aText);
}
a.click();
href = null;
};
/**
* Returns a file extension, or another string
* if the provided parameter has no extension.
*
* @param {String} filename
* @return {Array} [fileName, fileExtension]
*
* @private
*/
function _checkFileExtension(filename, extension) {
if (!extension || extension === true || extension === 'true') {
extension = '';
}
if (!filename) {
filename = 'untitled';
}
var ext = '';
// make sure the file will have a name, see if filename needs extension
if (filename && filename.indexOf('.') > -1) {
ext = filename.split('.').pop();
}
// append extension if it doesn't exist
if (extension) {
if (ext !== extension) {
ext = extension;
filename = filename + '.' + ext;
}
}
return [filename, ext];
}
p5.prototype._checkFileExtension = _checkFileExtension;
/**
* Returns true if the browser is Safari, false if not.
* Safari makes trouble for downloading files.
*
* @return {Boolean} [description]
* @private
*/
p5.prototype._isSafari = function() {
var x = Object.prototype.toString.call(window.HTMLElement);
return x.indexOf('Constructor') > 0;
};
/**
* Helper function, a callback for download that deletes
* an invisible anchor element from the DOM once the file
* has been automatically downloaded.
*
* @private
*/
function destroyClickedElement(event) {
document.body.removeChild(event.target);
}
module.exports = p5;
},{"../core/core":16,"../core/error_helpers":19,"reqwest":1}],39:[function(require,module,exports){
/**
* @module IO
* @submodule Table
* @requires core
*/
'use strict';
var p5 = require('../core/core');
/**
* Table Options
* Generic class for handling tabular data, typically from a
* CSV, TSV, or other sort of spreadsheet file.
* CSV files are
*
* comma separated values, often with the data in quotes. TSV
* files use tabs as separators, and usually don't bother with the
* quotes.
* File names should end with .csv if they're comma separated.
* A rough "spec" for CSV can be found
* here.
* To load files, use the loadTable method.
* To save tables to your computer, use the save method
* or the saveTable method.
*
* Possible options include:
*
* - csv - parse the table as comma-separated values
*
- tsv - parse the table as tab-separated values
*
- header - this table has a header (title) row
*
*/
/**
* Table objects store data with multiple rows and columns, much
* like in a traditional spreadsheet. Tables can be generated from
* scratch, dynamically, or using data from an existing file.
*
* @class p5.Table
* @constructor
* @param {Array} [rows] An array of p5.TableRow objects
* @return {p5.Table} p5.Table generated
*/
p5.Table = function (rows) {
/**
* @property columns
* @type {Array}
*/
this.columns = [];
/**
* @property rows
* @type {Array}
*/
this.rows = [];
};
/**
* Use addRow() to add a new row of data to a p5.Table object. By default,
* an empty row is created. Typically, you would store a reference to
* the new row in a TableRow object (see newRow in the example above),
* and then set individual values using set().
*
* If a p5.TableRow object is included as a parameter, then that row is
* duplicated and added to the table.
*
* @method addRow
* @param {p5.TableRow} [row] row to be added to the table
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* //add a row
* var newRow = table.addRow();
* newRow.setString("id", table.getRowCount() - 1);
* newRow.setString("species", "Canis Lupus");
* newRow.setString("name", "Wolf");
*
* //print the results
* for (var r = 0; r < table.getRowCount(); r++)
* for (var c = 0; c < table.getColumnCount(); c++)
* print(table.getString(r, c));
* }
*
*
*/
p5.Table.prototype.addRow = function(row) {
// make sure it is a valid TableRow
var r = row || new p5.TableRow();
if (typeof(r.arr) === 'undefined' || typeof(r.obj) === 'undefined') {
//r = new p5.prototype.TableRow(r);
throw 'invalid TableRow: ' + r;
}
r.table = this;
this.rows.push(r);
return r;
};
/**
* Removes a row from the table object.
*
* @method removeRow
* @param {Number} id ID number of the row to remove
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* //remove the first row
* var r = table.removeRow(0);
*
* //print the results
* for (var r = 0; r < table.getRowCount(); r++)
* for (var c = 0; c < table.getColumnCount(); c++)
* print(table.getString(r, c));
* }
*
*
*/
p5.Table.prototype.removeRow = function(id) {
this.rows[id].table = null; // remove reference to table
var chunk = this.rows.splice(id+1, this.rows.length);
this.rows.pop();
this.rows = this.rows.concat(chunk);
};
/**
* Returns a reference to the specified p5.TableRow. The reference
* can then be used to get and set values of the selected row.
*
* @method getRow
* @param {Number} rowID ID number of the row to get
* @return {TableRow} p5.TableRow object
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* var row = table.getRow(1);
* //print it column by column
* //note: a row is an object, not an array
* for (var c = 0; c < table.getColumnCount(); c++)
* print(row.getString(c));
* }
*
*
*/
p5.Table.prototype.getRow = function(r) {
return this.rows[r];
};
/**
* Gets all rows from the table. Returns an array of p5.TableRows.
*
* @method getRows
* @return {Array} Array of p5.TableRows
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* var rows = table.getRows();
*
* //warning: rows is an array of objects
* for (var r = 0; r < rows.length; r++)
* rows[r].set("name", "Unicorn");
*
* //print the results
* for (var r = 0; r < table.getRowCount(); r++)
* for (var c = 0; c < table.getColumnCount(); c++)
* print(table.getString(r, c));
* }
*
*
*/
p5.Table.prototype.getRows = function() {
return this.rows;
};
/**
* Finds the first row in the Table that contains the value
* provided, and returns a reference to that row. Even if
* multiple rows are possible matches, only the first matching
* row is returned. The column to search may be specified by
* either its ID or title.
*
* @method findRow
* @param {String} value The value to match
* @param {Number|String} column ID number or title of the
* column to search
* @return {TableRow}
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* //find the animal named zebra
* var row = table.findRow("Zebra", "name");
* //find the corresponding species
* print(row.getString("species"));
* }
*
*
*/
p5.Table.prototype.findRow = function(value, column) {
// try the Object
if (typeof(column) === 'string') {
for (var i = 0; i < this.rows.length; i++){
if (this.rows[i].obj[column] === value) {
return this.rows[i];
}
}
}
// try the Array
else {
for (var j = 0; j < this.rows.length; j++){
if (this.rows[j].arr[column] === value) {
return this.rows[j];
}
}
}
// otherwise...
return null;
};
/**
* Finds the rows in the Table that contain the value
* provided, and returns references to those rows. Returns an
* Array, so for must be used to iterate through all the rows,
* as shown in the example above. The column to search may be
* specified by either its ID or title.
*
* @method findRows
* @param {String} value The value to match
* @param {Number|String} column ID number or title of the
* column to search
* @return {Array} An Array of TableRow objects
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* //add another goat
* var newRow = table.addRow();
* newRow.setString("id", table.getRowCount() - 1);
* newRow.setString("species", "Scape Goat");
* newRow.setString("name", "Goat");
*
* //find the rows containing animals named Goat
* var rows = table.findRows("Goat", "name");
* print(rows.length + " Goats found");
* }
*
*
*/
p5.Table.prototype.findRows = function(value, column) {
var ret = [];
if (typeof(column) === 'string') {
for (var i = 0; i < this.rows.length; i++){
if (this.rows[i].obj[column] === value) {
ret.push( this.rows[i] );
}
}
}
// try the Array
else {
for (var j = 0; j < this.rows.length; j++){
if (this.rows[j].arr[column] === value) {
ret.push( this.rows[j] );
}
}
}
return ret;
};
/**
* Finds the first row in the Table that matches the regular
* expression provided, and returns a reference to that row.
* Even if multiple rows are possible matches, only the first
* matching row is returned. The column to search may be
* specified by either its ID or title.
*
* @method matchRow
* @param {String} regexp The regular expression to match
* @param {String|Number} column The column ID (number) or
* title (string)
* @return {TableRow} TableRow object
*/
p5.Table.prototype.matchRow = function(regexp, column) {
if (typeof(column) === 'number') {
for (var j = 0; j < this.rows.length; j++) {
if ( this.rows[j].arr[column].match(regexp) ) {
return this.rows[j];
}
}
}
else {
for (var i = 0; i < this.rows.length; i++) {
if ( this.rows[i].obj[column].match(regexp) ) {
return this.rows[i];
}
}
}
return null;
};
/**
* Finds the first row in the Table that matches the regular
* expression provided, and returns a reference to that row.
* Even if multiple rows are possible matches, only the first
* matching row is returned. The column to search may be specified
* by either its ID or title.
*
* @method matchRows
* @param {String} regexp The regular expression to match
* @param {String|Number} [column] The column ID (number) or
* title (string)
* @return {Array} An Array of TableRow objects
*/
p5.Table.prototype.matchRows = function(regexp, column) {
var ret = [];
if (typeof(column) === 'number') {
for (var j = 0; j < this.rows.length; j++) {
if ( this.rows[j].arr[column].match(regexp) ) {
ret.push( this.rows[j] );
}
}
}
else {
for (var i = 0; i < this.rows.length; i++) {
if ( this.rows[i].obj[column].match(regexp) ) {
ret.push( this.rows[i] );
}
}
}
return ret;
};
/**
* Retrieves all values in the specified column, and returns them
* as an array. The column may be specified by either its ID or title.
*
* @method getColumn
* @param {String|Number} column String or Number of the column to return
* @return {Array} Array of column values
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* //getColumn returns an array that can be printed directly
* print(table.getColumn("species"));
* //outputs ["Capra hircus", "Panthera pardus", "Equus zebra"]
* }
*
*
*/
p5.Table.prototype.getColumn = function(value) {
var ret = [];
if (typeof(value) === 'string'){
for (var i = 0; i < this.rows.length; i++){
ret.push (this.rows[i].obj[value]);
}
} else {
for (var j = 0; j < this.rows.length; j++){
ret.push (this.rows[j].arr[value]);
}
}
return ret;
};
/**
* Removes all rows from a Table. While all rows are removed,
* columns and column titles are maintained.
*
* @method clearRows
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* table.clearRows();
* print(table.getRowCount() + " total rows in table");
* print(table.getColumnCount() + " total columns in table");
* }
*
*
*/
p5.Table.prototype.clearRows = function() {
delete this.rows;
this.rows = [];
};
/**
* Use addColumn() to add a new column to a Table object.
* Typically, you will want to specify a title, so the column
* may be easily referenced later by name. (If no title is
* specified, the new column's title will be null.)
*
* @method addColumn
* @param {String} [title] title of the given column
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* table.addColumn("carnivore");
* table.set(0, "carnivore", "no");
* table.set(1, "carnivore", "yes");
* table.set(2, "carnivore", "no");
*
* //print the results
* for (var r = 0; r < table.getRowCount(); r++)
* for (var c = 0; c < table.getColumnCount(); c++)
* print(table.getString(r, c));
* }
*
*
*/
p5.Table.prototype.addColumn = function(title) {
var t = title || null;
this.columns.push(t);
};
/**
* Returns the total number of columns in a Table.
*
* @return {Number} Number of columns in this table
*/
p5.Table.prototype.getColumnCount = function() {
return this.columns.length;
};
/**
* Returns the total number of rows in a Table.
*
* @method getRowCount
* @return {Number} Number of rows in this table
*/
p5.Table.prototype.getRowCount = function() {
return this.rows.length;
};
/**
* Removes any of the specified characters (or "tokens").
*
* If no column is specified, then the values in all columns and
* rows are processed. A specific column may be referenced by
* either its ID or title.
*
* @method removeTokens
* @param {String} chars String listing characters to be removed
* @param {String|Number} [column] Column ID (number)
* or name (string)
*/
p5.Table.prototype.removeTokens = function(chars, column) {
var escape= function(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};
var charArray = [];
for (var i = 0; i < chars.length; i++) {
charArray.push( escape( chars.charAt(i) ) );
}
var regex = new RegExp(charArray.join('|'), 'g');
if (typeof(column) === 'undefined'){
for (var c = 0; c < this.columns.length; c++) {
for (var d = 0; d < this.rows.length; d++) {
var s = this.rows[d].arr[c];
s = s.replace(regex, '');
this.rows[d].arr[c] = s;
this.rows[d].obj[this.columns[c]] = s;
}
}
}
else if (typeof(column) === 'string'){
for (var j = 0; j < this.rows.length; j++) {
var val = this.rows[j].obj[column];
val = val.replace(regex, '');
this.rows[j].obj[column] = val;
var pos = this.columns.indexOf(column);
this.rows[j].arr[pos] = val;
}
}
else {
for (var k = 0; k < this.rows.length; k++) {
var str = this.rows[k].arr[column];
str = str.replace(regex, '');
this.rows[k].arr[column] = str;
this.rows[k].obj[this.columns[column]] = str;
}
}
};
/**
* Trims leading and trailing whitespace, such as spaces and tabs,
* from String table values. If no column is specified, then the
* values in all columns and rows are trimmed. A specific column
* may be referenced by either its ID or title.
*
* @method trim
* @param {String|Number} column Column ID (number)
* or name (string)
*/
p5.Table.prototype.trim = function(column) {
var regex = new RegExp( (' '), 'g');
if (typeof(column) === 'undefined'){
for (var c = 0; c < this.columns.length; c++) {
for (var d = 0; d < this.rows.length; d++) {
var s = this.rows[d].arr[c];
s = s.replace(regex, '');
this.rows[d].arr[c] = s;
this.rows[d].obj[this.columns[c]] = s;
}
}
}
else if (typeof(column) === 'string'){
for (var j = 0; j < this.rows.length; j++) {
var val = this.rows[j].obj[column];
val = val.replace(regex, '');
this.rows[j].obj[column] = val;
var pos = this.columns.indexOf(column);
this.rows[j].arr[pos] = val;
}
}
else {
for (var k = 0; k < this.rows.length; k++) {
var str = this.rows[k].arr[column];
str = str.replace(regex, '');
this.rows[k].arr[column] = str;
this.rows[k].obj[this.columns[column]] = str;
}
}
};
/**
* Use removeColumn() to remove an existing column from a Table
* object. The column to be removed may be identified by either
* its title (a String) or its index value (an int).
* removeColumn(0) would remove the first column, removeColumn(1)
* would remove the second column, and so on.
*
* @method removeColumn
* @param {String|Number} column columnName (string) or ID (number)
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* table.removeColumn("id");
* print(table.getColumnCount());
* }
*
*
*/
p5.Table.prototype.removeColumn = function(c) {
var cString;
var cNumber;
if (typeof(c) === 'string') {
// find the position of c in the columns
cString = c;
cNumber = this.columns.indexOf(c);
console.log('string');
}
else{
cNumber = c;
cString = this.columns[c];
}
var chunk = this.columns.splice(cNumber+1, this.columns.length);
this.columns.pop();
this.columns = this.columns.concat(chunk);
for (var i = 0; i < this.rows.length; i++){
var tempR = this.rows[i].arr;
var chip = tempR.splice(cNumber+1, tempR.length);
tempR.pop();
this.rows[i].arr = tempR.concat(chip);
delete this.rows[i].obj[cString];
}
};
/**
* Stores a value in the Table's specified row and column.
* The row is specified by its ID, while the column may be specified
* by either its ID or title.
*
* @method set
* @param {String|Number} column column ID (Number)
* or title (String)
* @param {String|Number} value value to assign
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* table.set(0, "species", "Canis Lupus");
* table.set(0, "name", "Wolf");
*
* //print the results
* for (var r = 0; r < table.getRowCount(); r++)
* for (var c = 0; c < table.getColumnCount(); c++)
* print(table.getString(r, c));
* }
*
*
*/
p5.Table.prototype.set = function(row, column, value) {
this.rows[row].set(column, value);
};
/**
* Stores a Float value in the Table's specified row and column.
* The row is specified by its ID, while the column may be specified
* by either its ID or title.
*
* @method setNum
* @param {Number} row row ID
* @param {String|Number} column column ID (Number)
* or title (String)
* @param {Number} value value to assign
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* table.setNum(1, "id", 1);
*
* print(table.getColumn(0));
* //["0", 1, "2"]
* }
*
*
*/
p5.Table.prototype.setNum = function(row, column, value){
this.rows[row].set(column, value);
};
/**
* Stores a String value in the Table's specified row and column.
* The row is specified by its ID, while the column may be specified
* by either its ID or title.
*
* @method setString
* @param {Number} row row ID
* @param {String|Number} column column ID (Number)
* or title (String)
* @param {String} value value to assign
*/
p5.Table.prototype.setString = function(row, column, value){
this.rows[row].set(column, value);
};
/**
* Retrieves a value from the Table's specified row and column.
* The row is specified by its ID, while the column may be specified by
* either its ID or title.
*
* @method get
* @param {Number} row row ID
* @param {String|Number} column columnName (string) or
* ID (number)
* @return {String|Number}
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* print(table.get(0, 1));
* //Capra hircus
* print(table.get(0, "species"));
* //Capra hircus
* }
*
*
*/
p5.Table.prototype.get = function(row, column) {
return this.rows[row].get(column);
};
/**
* Retrieves a Float value from the Table's specified row and column.
* The row is specified by its ID, while the column may be specified by
* either its ID or title.
*
* @method getNum
* @param {Number} row row ID
* @param {String|Number} column columnName (string) or
* ID (number)
* @return {Number}
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* print(table.getNum(1, 0) + 100);
* //id 1 + 100 = 101
* }
*
*
*/
p5.Table.prototype.getNum = function(row, column) {
return this.rows[row].getNum(column);
};
/**
* Retrieves a String value from the Table's specified row and column.
* The row is specified by its ID, while the column may be specified by
* either its ID or title.
*
* @method getString
* @param {Number} row row ID
* @param {String|Number} column columnName (string) or
* ID (number)
* @return {String}
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* var tableArray = table.getArray();
*
* //output each row as array
* for (var i = 0; i < tableArray.length; i++)
* print(tableArray[i]);
* }
*
*
*/
p5.Table.prototype.getString = function(row, column) {
return this.rows[row].getString(column);
};
/**
* Retrieves all table data and returns as an object. If a column name is
* passed in, each row object will be stored with that attribute as its
* title.
*
* @method getObject
* @param {String} headerColumn Name of the column which should be used to
* title each row object (optional)
* @return {Object}
*
* @example
*
*
* // Given the CSV file "mammals.csv"
* // in the project's "assets" folder:
* //
* // id,species,name
* // 0,Capra hircus,Goat
* // 1,Panthera pardus,Leopard
* // 2,Equus zebra,Zebra
*
* var table;
*
* function preload() {
* //my table is comma separated value "csv"
* //and has a header specifying the columns labels
* table = loadTable("assets/mammals.csv", "csv", "header");
* }
*
* function setup() {
* var tableObject = table.getObject();
*
* print(tableObject);
* //outputs an object
* }
*
*
*/
p5.Table.prototype.getObject = function (headerColumn) {
var tableObject = {};
var obj, cPos, index;
for(var i = 0; i < this.rows.length; i++) {
obj = this.rows[i].obj;
if (typeof(headerColumn) === 'string'){
cPos = this.columns.indexOf(headerColumn); // index of columnID
if (cPos >= 0) {
index = obj[headerColumn];
tableObject[index] = obj;
} else {
throw 'This table has no column named "' + headerColumn +'"';
}
} else {
tableObject[i] = this.rows[i].obj;
}
}
return tableObject;
};
/**
* Retrieves all table data and returns it as a multidimensional array.
*
* @method getArray
* @return {Array}
*/
p5.Table.prototype.getArray = function () {
var tableArray = [];
for(var i = 0; i < this.rows.length; i++) {
tableArray.push(this.rows[i].arr);
}
return tableArray;
};
module.exports = p5.Table;
},{"../core/core":16}],40:[function(require,module,exports){
/**
* @module IO
* @submodule Table
* @requires core
*/
'use strict';
var p5 = require('../core/core');
/**
* A TableRow object represents a single row of data values,
* stored in columns, from a table.
*
* A Table Row contains both an ordered array, and an unordered
* JSON object.
*
* @class p5.TableRow
* @constructor
* @param {String} [str] optional: populate the row with a
* string of values, separated by the
* separator
* @param {String} [separator] comma separated values (csv) by default
*/
p5.TableRow = function (str, separator) {
var arr = [];
var obj = {};
if (str){
separator = separator || ',';
arr = str.split(separator);
}
for (var i = 0; i < arr.length; i++){
var key = i;
var val = arr[i];
obj[key] = val;
}
this.arr = arr;
this.obj = obj;
this.table = null;
};
/**
* Stores a value in the TableRow's specified column.
* The column may be specified by either its ID or title.
*
* @method set
* @param {String|Number} column Column ID (Number)
* or Title (String)
* @param {String|Number} value The value to be stored
*/
p5.TableRow.prototype.set = function(column, value) {
// if typeof column is string, use .obj
if (typeof(column) === 'string'){
var cPos = this.table.columns.indexOf(column); // index of columnID
if (cPos >= 0) {
this.obj[column] = value;
this.arr[cPos] = value;
}
else {
throw 'This table has no column named "' + column +'"';
}
}
// if typeof column is number, use .arr
else {
if (column < this.table.columns.length) {
this.arr[column] = value;
var cTitle = this.table.columns[column];
this.obj[cTitle] = value;
}
else {
throw 'Column #' + column + ' is out of the range of this table';
}
}
};
/**
* Stores a Float value in the TableRow's specified column.
* The column may be specified by either its ID or title.
*
* @method setNum
* @param {String|Number} column Column ID (Number)
* or Title (String)
* @param {Number} value The value to be stored
* as a Float
*/
p5.TableRow.prototype.setNum = function(column, value){
var floatVal = parseFloat(value, 10);
this.set(column, floatVal);
};
/**
* Stores a String value in the TableRow's specified column.
* The column may be specified by either its ID or title.
*
* @method setString
* @param {String|Number} column Column ID (Number)
* or Title (String)
* @param {String} value The value to be stored
* as a String
*/
p5.TableRow.prototype.setString = function(column, value){
var stringVal = value.toString();
this.set(column, stringVal);
};
/**
* Retrieves a value from the TableRow's specified column.
* The column may be specified by either its ID or title.
*
* @method get
* @param {String|Number} column columnName (string) or
* ID (number)
* @return {String|Number}
*/
p5.TableRow.prototype.get = function(column) {
if (typeof(column) === 'string'){
return this.obj[column];
} else {
return this.arr[column];
}
};
/**
* Retrieves a Float value from the TableRow's specified
* column. The column may be specified by either its ID or
* title.
*
* @method getNum
* @param {String|Number} column columnName (string) or
* ID (number)
* @return {Number} Float Floating point number
*/
p5.TableRow.prototype.getNum = function(column) {
var ret;
if (typeof(column) === 'string'){
ret = parseFloat(this.obj[column], 10);
} else {
ret = parseFloat(this.arr[column], 10);
}
if (ret.toString() === 'NaN') {
throw 'Error: ' + this.obj[column]+ ' is NaN (Not a Number)';
}
return ret;
};
/**
* Retrieves an String value from the TableRow's specified
* column. The column may be specified by either its ID or
* title.
*
* @method getString
* @param {String|Number} column columnName (string) or
* ID (number)
* @return {String} String
*/
p5.TableRow.prototype.getString = function(column) {
if (typeof(column) === 'string'){
return this.obj[column].toString();
} else {
return this.arr[column].toString();
}
};
module.exports = p5.TableRow;
},{"../core/core":16}],41:[function(require,module,exports){
/**
* @module Math
* @submodule Calculation
* @for p5
* @requires core
*/
'use strict';
var p5 = require('../core/core');
/**
* Calculates the absolute value (magnitude) of a number. Maps to Math.abs().
* The absolute value of a number is always positive.
*
* @method abs
* @param {Number} n number to compute
* @return {Number} absolute value of given number
* @example
*
* function setup() {
* var x = -3;
* var y = abs(x);
*
* print(x); // -3
* print(y); // 3
* }
*
*/
p5.prototype.abs = Math.abs;
/**
* Calculates the closest int value that is greater than or equal to the
* value of the parameter. Maps to Math.ceil(). For example, ceil(9.03)
* returns the value 10.
*
* @method ceil
* @param {Number} n number to round up
* @return {Number} rounded up number
* @example
*
* function draw() {
* background(200);
* // map, mouseX between 0 and 5.
* var ax = map(mouseX, 0, 100, 0, 5);
* var ay = 66;
*
* //Get the ceiling of the mapped number.
* var bx = ceil(map(mouseX, 0, 100, 0,5));
* var by = 33;
*
* // Multiply the mapped numbers by 20 to more easily
* // see the changes.
* stroke(0);
* fill(0);
* line(0, ay, ax * 20, ay);
* line(0, by, bx * 20, by);
*
* // Reformat the float returned by map and draw it.
* noStroke();
* text(nfc(ax, 2,2), ax, ay - 5);
* text(nfc(bx,1,1), bx, by - 5);
* }
*
*/
p5.prototype.ceil = Math.ceil;
/**
* Constrains a value between a minimum and maximum value.
*
* @method constrain
* @param {Number} n number to constrain
* @param {Number} low minimum limit
* @param {Number} high maximum limit
* @return {Number} constrained number
* @example
*
* function draw() {
* background(200);
*
* var leftWall = 25;
* var rightWall = 75;
*
* // xm is just the mouseX, while
* // xc is the mouseX, but constrained
* // between the leftWall and rightWall!
* var xm = mouseX;
* var xc = constrain(mouseX, leftWall, rightWall);
*
* // Draw the walls.
* stroke(150);
* line(leftWall, 0, leftWall, height);
* line(rightWall, 0, rightWall, height);
*
* // Draw xm and xc as circles.
* noStroke();
* fill(150);
* ellipse(xm, 33, 9,9); // Not Constrained
* fill(0);
* ellipse(xc, 66, 9,9); // Constrained
* }
*
*/
p5.prototype.constrain = function(n, low, high) {
return Math.max(Math.min(n, high), low);
};
/**
* Calculates the distance between two points.
*
* @method dist
* @param {Number} x1 x-coordinate of the first point
* @param {Number} y1 y-coordinate of the first point
* @param {Number} x2 x-coordinate of the second point
* @param {Number} y2 y-coordinate of the second point
* @return {Number} distance between the two points
* @example
*
* // Move your mouse inside the canvas to see the
* // change in distance between two points!
* function draw() {
* background(200);
* fill(0);
*
* var x1 = 10;
* var y1 = 90;
* var x2 = mouseX;
* var y2 = mouseY;
*
* line(x1, y1, x2, y2);
* ellipse(x1, y1, 7, 7);
* ellipse(x2, y2, 7, 7);
*
* // d is the length of the line
* // the distance from point 1 to point 2.
* var d = int(dist(x1, y1, x2, y2));
*
* // Let's write d along the line we are drawing!
* push();
* translate( (x1+x2)/2, (y1+y2)/2 );
* rotate( atan2(y2-y1,x2-x1) );
* text(nfc(d,1,1), 0, -5);
* pop();
* // Fancy!
* }
*
*/
p5.prototype.dist = function(x1, y1, x2, y2) {
return Math.sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
};
/**
* Returns Euler's number e (2.71828...) raised to the power of the n
* parameter. Maps to Math.exp().
*
* @method exp
* @param {Number} n exponent to raise
* @return {Number} e^n
* @example
*
* function draw() {
* background(200);
*
* // Compute the exp() function with a value between 0 and 2
* var xValue = map(mouseX, 0, width, 0, 2);
* var yValue = exp(xValue);
*
* var y = map(yValue, 0, 8, height, 0);
*
* var legend = "exp (" + nfc(xValue, 3) +")\n= " + nf(yValue, 1, 4);
* stroke(150);
* line(mouseX, y, mouseX, height);
* fill(0);
* text(legend, 5, 15);
* noStroke();
* ellipse (mouseX,y, 7, 7);
*
* // Draw the exp(x) curve,
* // over the domain of x from 0 to 2
* noFill();
* stroke(0);
* beginShape();
* for (var x = 0; x < width; x++) {
* xValue = map(x, 0, width, 0, 2);
* yValue = exp(xValue);
* y = map(yValue, 0, 8, height, 0);
* vertex(x, y);
* }
*
* endShape();
* line(0, 0, 0, height);
* line(0, height-1, width, height-1);
* }
*
*/
p5.prototype.exp = Math.exp;
/**
* Calculates the closest int value that is less than or equal to the
* value of the parameter. Maps to Math.floor().
*
* @method floor
* @param {Number} n number to round down
* @return {Number} rounded down number
* @example
*
* function draw() {
* background(200);
* //map, mouseX between 0 and 5.
* var ax = map(mouseX, 0, 100, 0, 5);
* var ay = 66;
*
* //Get the floor of the mapped number.
* var bx = floor(map(mouseX, 0, 100, 0,5));
* var by = 33;
*
* // Multiply the mapped numbers by 20 to more easily
* // see the changes.
* stroke(0);
* fill(0);
* line(0, ay, ax * 20, ay);
* line(0, by, bx * 20, by);
*
* // Reformat the float returned by map and draw it.
* noStroke();
* text(nfc(ax, 2,2), ax, ay - 5);
* text(nfc(bx,1,1), bx, by - 5);
* }
*
*/
p5.prototype.floor = Math.floor;
/**
* Calculates a number between two numbers at a specific increment. The amt
* parameter is the amount to interpolate between the two values where 0.0
* equal to the first point, 0.1 is very near the first point, 0.5 is
* half-way in between, etc. The lerp function is convenient for creating
* motion along a straight path and for drawing dotted lines.
*
* @method lerp
* @param {Number} start first value
* @param {Number} stop second value
* @param {Number} amt number between 0.0 and 1.0
* @return {Number} lerped value
* @example
*
* function setup() {
* background(200);
* var a = 20;
* var b = 80;
* var c = lerp(a,b, .2);
* var d = lerp(a,b, .5);
* var e = lerp(a,b, .8);
*
* var y = 50
*
* strokeWeight(5);
* stroke(0); // Draw the original points in black
* point(a, y);
* int(b, y);
*
* stroke(100); // Draw the lerp points in gray
* point(c, y);
* point(d, y);
* point(e, y);
* }
*
*/
p5.prototype.lerp = function(start, stop, amt) {
return amt*(stop-start)+start;
};
/**
* Calculates the natural logarithm (the base-e logarithm) of a number. This
* function expects the n parameter to be a value greater than 0.0. Maps to
* Math.log().
*
* @method log
* @param {Number} n number greater than 0
* @return {Number} natural logarithm of n
* @example
*
* function draw() {
* background(200);
* var maxX = 2.8;
* var maxY = 1.5;
*
* // Compute the natural log of a value between 0 and maxX
* var xValue = map(mouseX, 0, width, 0, maxX);
* if (xValue > 0) { // Cannot take the log of a negative number.
* var yValue = log(xValue);
* var y = map(yValue, -maxY, maxY, height, 0);
*
* // Display the calculation occurring.
* var legend = "log(" + nf(xValue, 1, 2) + ")\n= " + nf(yValue, 1, 3);
* stroke(150);
* line(mouseX, y, mouseX, height);
* fill(0);
* text (legend, 5, 15);
* noStroke();
* ellipse (mouseX, y, 7, 7);
* }
*
* // Draw the log(x) curve,
* // over the domain of x from 0 to maxX
* noFill();
* stroke(0);
* beginShape();
* for(var x=0; x
*/
p5.prototype.log = Math.log;
/**
* Calculates the magnitude (or length) of a vector. A vector is a direction
* in space commonly used in computer graphics and linear algebra. Because it
* has no "start" position, the magnitude of a vector can be thought of as
* the distance from the coordinate 0,0 to its x,y value. Therefore, mag() is
* a shortcut for writing dist(0, 0, x, y).
*
* @method mag
* @param {Number} a first value
* @param {Number} b second value
* @return {Number} magnitude of vector from (0,0) to (a,b)
* @example
*
* function setup() {
* var x1 = 20;
* var x2 = 80;
* var y1 = 30;
* var y2 = 70;
*
* line(0, 0, x1, y1);
* print(mag(x1, y1)); // Prints "36.05551"
* line(0, 0, x2, y1);
* print(mag(x2, y1)); // Prints "85.44004"
* line(0, 0, x1, y2);
* print(mag(x1, y2)); // Prints "72.8011"
* line(0, 0, x2, y2);
* print(mag(x2, y2)); // Prints "106.30146"
* }
*
*/
p5.prototype.mag = function(x, y) {
return Math.sqrt(x*x+y*y);
};
/**
* Re-maps a number from one range to another.
* In the first example above, the number 25 is converted from a value in the
* range of 0 to 100 into a value that ranges from the left edge of the
* window (0) to the right edge (width).
*
* @method map
* @param {Number} value the incoming value to be converted
* @param {Number} start1 lower bound of the value's current range
* @param {Number} stop1 upper bound of the value's current range
* @param {Number} start2 lower bound of the value's target range
* @param {Number} stop upper bound of the value's target range
* @return {Number} remapped number
* @example
*
* createCanvas(200, 200);
* var value = 25;
* var m = map(value, 0, 100, 0, width);
* ellipse(m, 200, 10, 10);
*
*
*
* function setup() {
* createCanvs(200, 200);
* noStroke();
* }
*
* function draw() {
* background(204);
* var x1 = map(mouseX, 0, width, 50, 150);
* ellipse(x1, 75, 50, 50);
* var x2 = map(mouseX, 0, width, 0, 200);
* ellipse(x2, 125, 50, 50);
* }
*
*/
p5.prototype.map = function(n, start1, stop1, start2, stop2) {
return ((n-start1)/(stop1-start1))*(stop2-start2)+start2;
};
/**
* Determines the largest value in a sequence of numbers, and then returns
* that value. max() accepts any number of Number parameters, or an Array
* of any length.
*
* @method max
* @param {Number|Array} n0 Numbers to compare
* @return {Number} maximum Number
* @example
*
* function setup() {
* // Change the elements in the array and run the sketch
* // to show how max() works!
* numArray = new Array(2,1,5,4,8,9);
* fill(0);
* noStroke();
* text("Array Elements", 0, 10);
* // Draw all numbers in the array
* var spacing = 15;
* var elemsY = 25;
* for(var i = 0; i < numArray.length; i++) {
* text(numArray[i], i * spacing, elemsY);
* }
* maxX = 33;
* maxY = 80;
* // Draw the Maximum value in the array.
* textSize(32);
* text(max(numArray), maxX, maxY);
* }
*
*/
p5.prototype.max = function() {
if (arguments[0] instanceof Array) {
return Math.max.apply(null,arguments[0]);
} else {
return Math.max.apply(null,arguments);
}
};
/**
* Determines the smallest value in a sequence of numbers, and then returns
* that value. min() accepts any number of Number parameters, or an Array
* of any length.
*
* @method min
* @param {Number|Array} n0 Numbers to compare
* @return {Number} minimum Number
* @example
*
* function setup() {
* // Change the elements in the array and run the sketch
* // to show how min() works!
* numArray = new Array(2,1,5,4,8,9);
* fill(0);
* noStroke();
* text("Array Elements", 0, 10);
* // Draw all numbers in the array
* var spacing = 15;
* var elemsY = 25;
* for(var i = 0; i < numArray.length; i++) {
* text(numArray[i], i * spacing, elemsY);
* }
* maxX = 33;
* maxY = 80;
* // Draw the Minimum value in the array.
* textSize(32);
* text(min(numArray), maxX, maxY);
* }
*
*/
p5.prototype.min = function() {
if (arguments[0] instanceof Array) {
return Math.min.apply(null,arguments[0]);
} else {
return Math.min.apply(null,arguments);
}
};
/**
* Normalizes a number from another range into a value between 0 and 1.
* Identical to map(value, low, high, 0, 1).
* Numbers outside of the range are not clamped to 0 and 1, because
* out-of-range values are often intentional and useful. (See the second
* example above.)
*
* @method norm
* @param {Number} value incoming value to be normalized
* @param {Number} start lower bound of the value's current range
* @param {Number} stop upper bound of the value's current range
* @return {Number} normalized number
* @example
*
* function draw() {
* background(200);
* currentNum = mouseX;
* lowerBound = 0;
* upperBound = width; //100;
* normalized = norm(currentNum, lowerBound, upperBound);
* lineY = 70
* line(0, lineY, width, lineY);
* //Draw an ellipse mapped to the non-normalized value.
* noStroke();
* fill(50)
* var s = 7; // ellipse size
* ellipse(currentNum, lineY, s, s);
*
* // Draw the guide
* guideY = lineY + 15;
* text("0", 0, guideY);
* textAlign(RIGHT);
* text("100", width, guideY);
*
* // Draw the normalized value
* textAlign(LEFT);
* fill(0);
* textSize(32);
* normalY = 40;
* normalX = 20;
* text(normalized, normalX, normalY);
* }
*
*/
p5.prototype.norm = function(n, start, stop) {
return this.map(n, start, stop, 0, 1);
};
/**
* Facilitates exponential expressions. The pow() function is an efficient
* way of multiplying numbers by themselves (or their reciprocals) in large
* quantities. For example, pow(3, 5) is equivalent to the expression
* 3*3*3*3*3 and pow(3, -5) is equivalent to 1 / 3*3*3*3*3. Maps to
* Math.pow().
*
* @method pow
* @param {Number} n base of the exponential expression
* @param {Number} e power by which to raise the base
* @return {Number} n^e
* @example
*
* function setup() {
* //Exponentially increase the size of an ellipse.
* eSize = 3; // Original Size
* eLoc = 10; // Original Location
*
* ellipse(eLoc, eLoc, eSize, eSize);
*
* ellipse(eLoc*2, eLoc*2, pow(eSize, 2), pow(eSize, 2));
*
* ellipse(eLoc*4, eLoc*4, pow(eSize, 3), pow(eSize, 3));
*
* ellipse(eLoc*8, eLoc*8, pow(eSize, 4), pow(eSize, 4));
* }
*
*/
p5.prototype.pow = Math.pow;
/**
* Calculates the integer closest to the n parameter. For example,
* round(133.8) returns the value 134. Maps to Math.round().
*
* @method round
* @param {Number} n number to round
* @return {Number} rounded number
* @example
*
* function draw() {
* background(200);
* //map, mouseX between 0 and 5.
* var ax = map(mouseX, 0, 100, 0, 5);
* var ay = 66;
*
* // Round the mapped number.
* var bx = round(map(mouseX, 0, 100, 0,5));
* var by = 33;
*
* // Multiply the mapped numbers by 20 to more easily
* // see the changes.
* stroke(0);
* fill(0);
* line(0, ay, ax * 20, ay);
* line(0, by, bx * 20, by);
*
* // Reformat the float returned by map and draw it.
* noStroke();
* text(nfc(ax, 2,2), ax, ay - 5);
* text(nfc(bx,1,1), bx, by - 5);
* }
*
*/
p5.prototype.round = Math.round;
/**
* Squares a number (multiplies a number by itself). The result is always a
* positive number, as multiplying two negative numbers always yields a
* positive result. For example, -1 * -1 = 1.
*
* @method sq
* @param {Number} n number to square
* @return {Number} squared number
* @example
*
* function draw() {
* background(200);
* eSize = 7;
* x1 = map(mouseX, 0, width, 0, 10);
* y1 = 80;
* x2 = sq(x1);
* y2 = 20;
*
* // Draw the non-squared.
* line(0, y1, width, y1);
* ellipse(x1, y1, eSize, eSize);
*
* // Draw the squared.
* line(0, y2, width, y2);
* ellipse(x2, y2, eSize, eSize);
*
* // Draw dividing line.
* stroke(100)
* line(0, height/2, width, height/2);
*
* // Draw text.
* noStroke();
* fill(0);
* text("x = " + x1, 0, y1 + spacing);
* text("sqrt(x) = " + x2, 0, y2 + spacing);
* }
*
*/
p5.prototype.sq = function(n) { return n*n; };
/**
* Calculates the square root of a number. The square root of a number is
* always positive, even though there may be a valid negative root. The
* square root s of number a is such that s*s = a. It is the opposite of
* squaring. Maps to Math.sqrt().
*
* @method sqrt
* @param {Number} n non-negative number to square root
* @return {Number} square root of number
* @example
*
* function draw() {
* background(200);
* eSize = 7;
* x1 = mouseX;
* y1 = 80;
* x2 = sqrt(x1);
* y2 = 20;
*
* // Draw the non-squared.
* line(0, y1, width, y1);
* ellipse(x1, y1, eSize, eSize);
*
* // Draw the squared.
* line(0, y2, width, y2);
* ellipse(x2, y2, eSize, eSize);
*
* // Draw dividing line.
* stroke(100)
* line(0, height/2, width, height/2);
*
* // Draw text.
* noStroke();
* fill(0);
* var spacing = 15;
* text("x = " + x1, 0, y1 + spacing);
* text("sqrt(x) = " + x2, 0, y2 + spacing);
* }
*
*/
p5.prototype.sqrt = Math.sqrt;
module.exports = p5;
},{"../core/core":16}],42:[function(require,module,exports){
/**
* @module Math
* @submodule Math
* @for p5
* @requires core
*/
'use strict';
var p5 = require('../core/core');
/**
* Creates a new p5.Vector (the datatype for storing vectors). This provides a
* two or three dimensional vector, specifically a Euclidean (also known as
* geometric) vector. A vector is an entity that has both magnitude and
* direction.
*
* @method createVector
* @param {Number} [x] x component of the vector
* @param {Number} [y] y component of the vector
* @param {Number} [z] z component of the vector
*/
p5.prototype.createVector = function (x, y, z) {
if (this instanceof p5) {
return new p5.Vector(this, arguments);
} else {
return new p5.Vector(x, y, z);
}
};
module.exports = p5;
},{"../core/core":16}],43:[function(require,module,exports){
//////////////////////////////////////////////////////////////
// http://mrl.nyu.edu/~perlin/noise/
// Adapting from PApplet.java
// which was adapted from toxi
// which was adapted from the german demo group farbrausch
// as used in their demo "art": http://www.farb-rausch.de/fr010src.zip
// someday we might consider using "improved noise"
// http://mrl.nyu.edu/~perlin/paper445.pdf
// See: https://github.com/shiffman/The-Nature-of-Code-Examples-p5.js/
// blob/master/introduction/Noise1D/noise.js
/**
* @module Math
* @submodule Noise
* @for p5
* @requires core
*/
'use strict';
var p5 = require('../core/core');
var PERLIN_YWRAPB = 4;
var PERLIN_YWRAP = 1<
>= 1;
var perlin;
/**
* Returns the Perlin noise value at specified coordinates. Perlin noise is
* a random sequence generator producing a more natural ordered, harmonic
* succession of numbers compared to the standard random() function.
* It was invented by Ken Perlin in the 1980s and been used since in
* graphical applications to produce procedural textures, natural motion,
* shapes, terrains etc.
The main difference to the
* random() function is that Perlin noise is defined in an infinite
* n-dimensional space where each pair of coordinates corresponds to a
* fixed semi-random value (fixed only for the lifespan of the program).
* The resulting value will always be between 0.0 and 1.0. p5.js can
* compute 1D, 2D and 3D noise, depending on the number of coordinates
* given. The noise value can be animated by moving through the noise space
* as demonstrated in the example above. The 2nd and 3rd dimension can also
* be interpreted as time.
The actual noise is structured
* similar to an audio signal, in respect to the function's use of
* frequencies. Similar to the concept of harmonics in physics, perlin
* noise is computed over several octaves which are added together for the
* final result.
Another way to adjust the character of the
* resulting sequence is the scale of the input coordinates. As the
* function works within an infinite space the value of the coordinates
* doesn't matter as such, only the distance between successive coordinates
* does (eg. when using noise() within a loop). As a general rule
* the smaller the difference between coordinates, the smoother the
* resulting noise sequence will be. Steps of 0.005-0.03 work best for most
* applications, but this will differ depending on use.
*
*
* @method noise
* @param {Number} x x-coordinate in noise space
* @param {Number} y y-coordinate in noise space
* @param {Number} z z-coordinate in noise space
* @return {Number} Perlin noise value (between 0 and 1) at specified
* coordinates
* @example
*
* var xoff = 0.0;
*
* function draw() {
* background(204);
* xoff = xoff + .01;
* var n = noise(xoff) * width;
* line(n, 0, n, height);
* }
*
*
*
* var noiseScale=0.02;
*
* function draw() {
* background(0);
* for (var x=0; x < width; x++) {
* var noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale);
* stroke(noiseVal*255);
* line(x, mouseY+noiseVal*80, x, height);
* }
* }
*
*
*/
p5.prototype.noise = function(x,y,z) {
// is this legit?
y = y || 0;
z = z || 0;
if (perlin == null) {
// need to deal with seeding?
//if (perlinRandom == null) {
//perlinRandom = new Random();
//}
perlin = new Array(PERLIN_SIZE + 1);
for (var i = 0; i < PERLIN_SIZE + 1; i++) {
perlin[i] = Math.random();
}
}
if (x<0) { x=-x; }
if (y<0) { y=-y; }
if (z<0) { z=-z; }
var xi=Math.floor(x), yi=Math.floor(y), zi=Math.floor(z);
var xf = x - xi;
var yf = y - yi;
var zf = z - zi;
var rxf, ryf;
var r=0;
var ampl=0.5;
var n1,n2,n3;
// Is this right do just have this here?
var noise_fsc = function(i) {
// using cosine lookup table
return 0.5*(1.0-cosLUT[Math.floor(i*perlin_PI)%SINCOS_LENGTH]);
};
for (var o=0; o=1.0) { xi++; xf--; }
if (yf>=1.0) { yi++; yf--; }
if (zf>=1.0) { zi++; zf--; }
}
return r;
};
// [toxi 040903]
// make perlin noise quality user controlled to allow
// for different levels of detail. lower values will produce
// smoother results as higher octaves are suppressed
/**
*
* Adjusts the character and level of detail produced by the Perlin noise
* function. Similar to harmonics in physics, noise is computed over
* several octaves. Lower octaves contribute more to the output signal and
* as such define the overall intensity of the noise, whereas higher octaves
* create finer grained details in the noise sequence. By default, noise is
* computed over 4 octaves with each octave contributing exactly half than
* its predecessor, starting at 50% strength for the 1st octave. This
* falloff amount can be changed by adding an additional function
* parameter. Eg. a falloff factor of 0.75 means each octave will now have
* 75% impact (25% less) of the previous lower octave. Any value between
* 0.0 and 1.0 is valid, however note that values greater than 0.5 might
* result in greater than 1.0 values returned by noise().
By changing these parameters, the signal created by the noise()
* function can be adapted to fit very specific needs and characteristics.
*
* @method noiseDetail
* @param {Number} lod number of octaves to be used by the noise
* @param {Number} falloff falloff factor for each octave
* @example
*
*
*
* var noiseVal;
* var noiseScale=0.02;
*
* function setup() {
* createCanvas(100,100);
* }
*
* function draw() {
* background(0);
* for (var y = 0; y < height; y++) {
* for (var x = 0; x < width/2; x++) {
* noiseDetail(2,0.2);
* noiseVal = noise((mouseX+x) * noiseScale,
* (mouseY+y) * noiseScale);
* stroke(noiseVal*255);
* point(x,y);
* noiseDetail(8,0.65);
* noiseVal = noise((mouseX + x + width/2) * noiseScale,
* (mouseY + y) * noiseScale);
* stroke(noiseVal*255);
* point(x + width/2, y);
* }
* }
* }
*
*
*/
p5.prototype.noiseDetail = function(lod, falloff) {
if (lod>0) { perlin_octaves=lod; }
if (falloff>0) { perlin_amp_falloff=falloff; }
};
/**
* Sets the seed value for noise(). By default, noise()
* produces different results each time the program is run. Set the
* value parameter to a constant to return the same pseudo-random
* numbers each time the software is run.
*
* @method noiseSeed
* @param {Number} seed the seed value
* @example
*
* var xoff = 0.0;
*
* function setup() {
* noiseSeed(99);
* stroke(0, 10);
* }
*
* function draw() {
* xoff = xoff + .01;
* var n = noise(xoff) * width;
* line(n, 0, n, height);
* }
*
*
*/
p5.prototype.noiseSeed = function(seed) {
// Linear Congruential Generator
// Variant of a Lehman Generator
var lcg = (function() {
// Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
// m is basically chosen to be large (as it is the max period)
// and for its relationships to a and c
var m = 4294967296,
// a - 1 should be divisible by m's prime factors
a = 1664525,
// c and m should be co-prime
c = 1013904223,
seed, z;
return {
setSeed : function(val) {
// pick a random seed if val is undefined or null
// the >>> 0 casts the seed to an unsigned 32-bit integer
z = seed = (val == null ? Math.random() * m : val) >>> 0;
},
getSeed : function() {
return seed;
},
rand : function() {
// define the recurrence relationship
z = (a * z + c) % m;
// return a float in [0, 1)
// if z = m then z / m = 0 therefore (z % m) / m < 1 always
return z / m;
}
};
}());
lcg.setSeed(seed);
perlin = new Array(PERLIN_SIZE + 1);
for (var i = 0; i < PERLIN_SIZE + 1; i++) {
perlin[i] = lcg.rand();
}
};
module.exports = p5;
},{"../core/core":16}],44:[function(require,module,exports){
/**
* @module Math
* @submodule Math
* @requires constants
*/
'use strict';
var p5 = require('../core/core');
var polarGeometry = require('./polargeometry');
var constants = require('../core/constants');
/**
* A class to describe a two or three dimensional vector, specifically
* a Euclidean (also known as geometric) vector. A vector is an entity
* that has both magnitude and direction. The datatype, however, stores
* the components of the vector (x,y for 2D, and x,y,z for 3D). The magnitude
* and direction can be accessed via the methods mag() and heading(). In many
* of the p5.js examples, you will see p5.Vector used to describe a position,
* velocity, or acceleration. For example, if you consider a rectangle moving
* across the screen, at any given instant it has a position (a vector that
* points from the origin to its location), a velocity (the rate at which the
* object's position changes per time unit, expressed as a vector), and
* acceleration (the rate at which the object's velocity changes per time
* unit, expressed as a vector). Since vectors represent groupings of values,
* we cannot simply use traditional addition/multiplication/etc. Instead,
* we'll need to do some "vector" math, which is made easy by the methods
* inside the p5.Vector class.
*
* @class p5.Vector
* @constructor
* @param {Number} [x] x component of the vector
* @param {Number} [y] y component of the vector
* @param {Number} [z] z component of the vector
* @example
*
*
* var v1 = createVector(40, 50);
* var v2 = createVector(40, 50);
*
* ellipse(v1.x, v1.y, 50, 50);
* ellipse(v2.x, v2.y, 50, 50);
* v1.add(v2);
* ellipse(v1.x, v1.y, 50, 50);
*
*
*/
p5.Vector = function() {
var x,y,z;
// This is how it comes in with createVector()
if(arguments[0] instanceof p5) {
// save reference to p5 if passed in
this.p5 = arguments[0];
x = arguments[1][0] || 0;
y = arguments[1][1] || 0;
z = arguments[1][2] || 0;
// This is what we'll get with new p5.Vector()
} else {
x = arguments[0] || 0;
y = arguments[1] || 0;
z = arguments[2] || 0;
}
/**
* The x component of the vector
* @property x
* @type {Number}
*/
this.x = x;
/**
* The y component of the vector
* @property y
* @type {Number}
*/
this.y = y;
/**
* The z component of the vector
* @property z
* @type {Number}
*/
this.z = z;
};
/**
* Returns a string representation of a vector v by calling String(v)
* or v.toString(). This method is useful for logging vectors in the
* console.
* @method toString
* @example
*
* function setup() {
* var v = createVector(20,30);
* print(String(v)); // prints "p5.Vector Object : [20, 30, 0]"
* }
*
*
*/
p5.Vector.prototype.toString = function p5VectorToString() {
return 'p5.Vector Object : ['+ this.x +', '+ this.y +', '+ this.z + ']';
};
/**
* Sets the x, y, and z component of the vector using two or three separate
* variables, the data from a p5.Vector, or the values from a float array.
* @method set
*
* @param {Number|p5.Vector|Array} [x] the x component of the vector or a
* p5.Vector or an Array
* @param {Number} [y] the y component of the vector
* @param {Number} [z] the z component of the vector
* @example
*
*
* function setup() {
* var v = createVector(1, 2, 3);
* v.set(4,5,6); // Sets vector to [4, 5, 6]
*
* var v1 = createVector(0, 0, 0);
* var arr = [1, 2, 3];
* v1.set(arr); // Sets vector to [1, 2, 3]
* }
*
*
*/
p5.Vector.prototype.set = function (x, y, z) {
if (x instanceof p5.Vector) {
this.x = x.x || 0;
this.y = x.y || 0;
this.z = x.z || 0;
return this;
}
if (x instanceof Array) {
this.x = x[0] || 0;
this.y = x[1] || 0;
this.z = x[2] || 0;
return this;
}
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
return this;
};
/**
* Gets a copy of the vector, returns a p5.Vector object.
*
* @method copy
* @return {p5.Vector} the copy of the p5.Vector object
* @example
*
*
* var v1 = createVector(1, 2, 3);
* var v2 = v.copy();
* print(v1.x == v2.x && v1.y == v2.y && v1.z == v2.z);
* // Prints "true"
*
*
*/
p5.Vector.prototype.copy = function () {
if (this.p5) {
return new p5.Vector(this.p5,[this.x, this.y, this.z]);
} else {
return new p5.Vector(this.x,this.y,this.z);
}
};
/**
* Adds x, y, and z components to a vector, adds one vector to another, or
* adds two independent vectors together. The version of the method that adds
* two vectors together is a static method and returns a p5.Vector, the others
* acts directly on the vector. See the examples for more context.
*
* @method add
* @chainable
* @param {Number|p5.Vector|Array} x the x component of the vector to be
* added or a p5.Vector or an Array
* @param {Number} [y] the y component of the vector to be
* added
* @param {Number} [z] the z component of the vector to be
* added
* @return {p5.Vector} the p5.Vector object.
* @example
*
*
* var v = createVector(1, 2, 3);
* v.add(4,5,6);
* // v's compnents are set to [5, 7, 9]
*
*
*
*
* // Static method
* var v1 = createVector(1, 2, 3);
* var v2 = createVector(2, 3, 4);
*
* var v3 = p5.Vector.add(v1, v2);
* // v3 has components [3, 5, 7]
*
*
*/
p5.Vector.prototype.add = function (x, y, z) {
if (x instanceof p5.Vector) {
this.x += x.x || 0;
this.y += x.y || 0;
this.z += x.z || 0;
return this;
}
if (x instanceof Array) {
this.x += x[0] || 0;
this.y += x[1] || 0;
this.z += x[2] || 0;
return this;
}
this.x += x || 0;
this.y += y || 0;
this.z += z || 0;
return this;
};
/**
* Subtracts x, y, and z components from a vector, subtracts one vector from
* another, or subtracts two independent vectors. The version of the method
* that subtracts two vectors is a static method and returns a p5.Vector, the
* other acts directly on the vector. See the examples for more context.
*
* @method sub
* @chainable
* @param {Number|p5.Vector|Array} x the x component of the vector or a
* p5.Vector or an Array
* @param {Number} [y] the y component of the vector
* @param {Number} [z] the z component of the vector
* @return {p5.Vector} p5.Vector object.
* @example
*
*
* var v = createVector(4, 5, 6);
* v.sub(1, 1, 1);
* // v's compnents are set to [3, 4, 5]
*
*
*
*
*
* // Static method
* var v1 = createVector(2, 3, 4);
* var v2 = createVector(1, 2, 3);
*
* var v3 = p5.Vector.sub(v1, v2);
* // v3 has compnents [1, 1, 1]
*
*
*/
p5.Vector.prototype.sub = function (x, y, z) {
if (x instanceof p5.Vector) {
this.x -= x.x || 0;
this.y -= x.y || 0;
this.z -= x.z || 0;
return this;
}
if (x instanceof Array) {
this.x -= x[0] || 0;
this.y -= x[1] || 0;
this.z -= x[2] || 0;
return this;
}
this.x -= x || 0;
this.y -= y || 0;
this.z -= z || 0;
return this;
};
/**
* Multiply the vector by a scalar. The static version of this method
* creates a new p5.Vector while the non static version acts on the vector
* directly. See the examples for more context.
*
* @method mult
* @chainable
* @param {Number} n the number to multiply with the vector
* @return {p5.Vector} a reference to the p5.Vector object (allow chaining)
* @example
*
*
* var v = createVector(1, 2, 3);
* v.mult(2);
* // v's compnents are set to [2, 4, 6]
*
*
*
*
*
* // Static method
* var v1 = createVector(1, 2, 3);
* var v2 = p5.Vector.mult(v1, 2);
* // v2 has compnents [2, 4, 6]
*
*
*/
p5.Vector.prototype.mult = function (n) {
this.x *= n || 0;
this.y *= n || 0;
this.z *= n || 0;
return this;
};
/**
* Divide the vector by a scalar. The static version of this method creates a
* new p5.Vector while the non static version acts on the vector directly.
* See the examples for more context.
*
* @method div
* @chainable
* @param {number} n the number to divide the vector by
* @return {p5.Vector} a reference to the p5.Vector object (allow chaining)
* @example
*
*
* var v = createVector(6, 4, 2);
* v.div(2); //v's compnents are set to [3, 2, 1]
*
*
*
*
*
* // Static method
* var v1 = createVector(6, 4, 2);
* var v2 = p5.Vector.div(v, 2);
* // v2 has compnents [3, 2, 1]
*
*
*/
p5.Vector.prototype.div = function (n) {
this.x /= n;
this.y /= n;
this.z /= n;
return this;
};
/**
* Calculates the magnitude (length) of the vector and returns the result as
* a float (this is simply the equation sqrt(x*x + y*y + z*z).)
*
* @method mag
* @return {Number} magnitude of the vector
* @example
*
*
* var v = createVector(20.0, 30.0, 40.0);
* var m = v.mag(10);
* print(m); // Prints "53.85164807134504"
*
*
*/
p5.Vector.prototype.mag = function () {
return Math.sqrt(this.magSq());
};
/**
* Calculates the squared magnitude of the vector and returns the result
* as a float (this is simply the equation (x*x + y*y + z*z).)
* Faster if the real length is not required in the
* case of comparing vectors, etc.
*
* @method magSq
* @return {number} squared magnitude of the vector
* @example
*
*
* // Static method
* var v1 = createVector(6, 4, 2);
* print(v1.magSq()); // Prints "56"
*
*
*/
p5.Vector.prototype.magSq = function () {
var x = this.x, y = this.y, z = this.z;
return (x * x + y * y + z * z);
};
/**
* Calculates the dot product of two vectors. The version of the method
* that computes the dot product of two independent vectors is a static
* method. See the examples for more context.
*
*
* @method dot
* @param {Number|p5.Vector} x x component of the vector or a p5.Vector
* @param {Number} [y] y component of the vector
* @param {Number} [z] z component of the vector
* @return {Number} the dot product
*
* @example
*
*
* var v1 = createVector(1, 2, 3);
* var v2 = createVector(2, 3, 4);
*
* print(v1.dot(v2)); // Prints "20"
*
*
*
*
*
* //Static method
* var v1 = createVector(1, 2, 3);
* var v2 = createVector(3, 2, 1);
* print (p5.Vector.dot(v1, v2)); // Prints "10"
*
*
*/
p5.Vector.prototype.dot = function (x, y, z) {
if (x instanceof p5.Vector) {
return this.dot(x.x, x.y, x.z);
}
return this.x * (x || 0) +
this.y * (y || 0) +
this.z * (z || 0);
};
/**
* Calculates and returns a vector composed of the cross product between
* two vectors. Both the static and non static methods return a new p5.Vector.
* See the examples for more context.
*
* @method cross
* @param {p5.Vector} v p5.Vector to be crossed
* @return {p5.Vector} p5.Vector composed of cross product
* @example
*
*
* var v1 = createVector(1, 2, 3);
* var v2 = createVector(1, 2, 3);
*
* v1.cross(v2); // v's components are [0, 0, 0]
*
*
*
*
*
* // Static method
* var v1 = createVector(1, 0, 0);
* var v2 = createVector(0, 1, 0);
*
* var crossProduct = p5.Vector.cross(v1, v2);
* // crossProduct has components [0, 0, 1]
*
*
*/
p5.Vector.prototype.cross = function (v) {
var x = this.y * v.z - this.z * v.y;
var y = this.z * v.x - this.x * v.z;
var z = this.x * v.y - this.y * v.x;
if (this.p5) {
return new p5.Vector(this.p5,[x,y,z]);
} else {
return new p5.Vector(x,y,z);
}
};
/**
* Calculates the Euclidean distance between two points (considering a
* point as a vector object).
*
* @method dist
* @param {p5.Vector} v the x, y, and z coordinates of a p5.Vector
* @return {Number} the distance
* @example
*
*
* var v1 = createVector(1, 0, 0);
* var v2 = createVector(0, 1, 0);
*
* var distance = v1.dist(v2); // distance is 1.4142...
*
*
*
*
* // Static method
* var v1 = createVector(1, 0, 0);
* var v2 = createVector(0, 1, 0);
*
* var distance = p5.Vector.dist(v1,v2);
* // distance is 1.4142...
*
*
*/
p5.Vector.prototype.dist = function (v) {
var d = v.copy().sub(this);
return d.mag();
};
/**
* Normalize the vector to length 1 (make it a unit vector).
*
* @method normalize
* @return {p5.Vector} normalized p5.Vector
* @example
*
*
* var v = createVector(10, 20, 2);
* // v has compnents [10.0, 20.0, 2.0]
* v.normalize();
* // v's compnents are set to
* // [0.4454354, 0.8908708, 0.089087084]
*
*
*
*/
p5.Vector.prototype.normalize = function () {
return this.div(this.mag());
};
/**
* Limit the magnitude of this vector to the value used for the max
* parameter.
*
* @method limit
* @param {Number} max the maximum magnitude for the vector
* @return {p5.Vector} the modified p5.Vector
* @example
*
*
* var v = createVector(10, 20, 2);
* // v has compnents [10.0, 20.0, 2.0]
* v.limit(5);
* // v's compnents are set to
* // [2.2271771, 4.4543543, 0.4454354]
*
*
*/
p5.Vector.prototype.limit = function (l) {
var mSq = this.magSq();
if(mSq > l*l) {
this.div(Math.sqrt(mSq)); //normalize it
this.mult(l);
}
return this;
};
/**
* Set the magnitude of this vector to the value used for the len
* parameter.
*
* @method setMag
* @param {number} len the new length for this vector
* @return {p5.Vector} the modified p5.Vector
* @example
*
*
* var v1 = createVector(10, 20, 2);
* // v has compnents [10.0, 20.0, 2.0]
* v1.setMag(10);
* // v's compnents are set to [6.0, 8.0, 0.0]
*
*
*/
p5.Vector.prototype.setMag = function (n) {
return this.normalize().mult(n);
};
/**
* Calculate the angle of rotation for this vector (only 2D vectors)
*
* @method heading
* @return {Number} the angle of rotation
* @example
*
* function setup() {
* var v1 = createVector(30,50);
* print(v1.heading()); // 1.0303768265243125
*
* var v1 = createVector(40,50);
* print(v1.heading()); // 0.8960553845713439
*
* var v1 = createVector(30,70);
* print(v1.heading()); // 1.1659045405098132
* }
*
*/
p5.Vector.prototype.heading = function () {
var h = Math.atan2(this.y, this.x);
if (this.p5) {
if (this.p5._angleMode === constants.RADIANS) {
return h;
} else {
return polarGeometry.radiansToDegrees(h);
}
} else {
return h;
}
};
/**
* Rotate the vector by an angle (only 2D vectors), magnitude remains the
* same
*
* @method rotate
* @param {number} angle the angle of rotation
* @return {p5.Vector} the modified p5.Vector
* @example
*
*
* var v = createVector(10.0, 20.0);
* // v has compnents [10.0, 20.0, 0.0]
* v.rotate(HALF_PI);
* // v's compnents are set to [-20.0, 9.999999, 0.0]
*
*
*/
p5.Vector.prototype.rotate = function (a) {
if (this.p5) {
if (this.p5._angleMode === constants.DEGREES) {
a = polarGeometry.degreesToRadians(a);
}
}
var newHeading = this.heading() + a;
var mag = this.mag();
this.x = Math.cos(newHeading) * mag;
this.y = Math.sin(newHeading) * mag;
return this;
};
/**
* Linear interpolate the vector to another vector
*
* @method lerp
* @param {p5.Vector} x the x component or the p5.Vector to lerp to
* @param {p5.Vector} [y] y the y component
* @param {p5.Vector} [z] z the z component
* @param {Number} amt the amount of interpolation; some value between 0.0
* (old vector) and 1.0 (new vector). 0.1 is very near
* the new vector. 0.5 is halfway in between.
* @return {p5.Vector} the modified p5.Vector
* @example
*
*
* var v = createVector(1, 1, 0);
*
* v.lerp(3, 3, 0, 0.5); // v now has components [2,2,0]
*
*
*
*
*
* var v1 = createVector(0, 0, 0);
* var v2 = createVector(100, 100, 0);
*
* var v3 = p5.Vector.lerp(v1, v2, 0.5);
* // v3 has components [50,50,0]
*
*
*/
p5.Vector.prototype.lerp = function (x, y, z, amt) {
if (x instanceof p5.Vector) {
return this.lerp(x.x, x.y, x.z, y);
}
this.x += (x - this.x) * amt || 0;
this.y += (y - this.y) * amt || 0;
this.z += (z - this.z) * amt || 0;
return this;
};
/**
* Return a representation of this vector as a float array. This is only
* for temporary use. If used in any other fashion, the contents should be
* copied by using the p5.Vector.copy() method to copy into your own
* array.
*
* @method array
* @return {Array} an Array with the 3 values
* @example
*
* function setup() {
* var v = createVector(20,30);
* print(v.array()); // Prints : Array [20, 30, 0]
* }
*
*
*
* var v = createVector(10.0, 20.0, 30.0);
* var f = v.array();
* print(f[0]); // Prints "10.0"
* print(f[1]); // Prints "20.0"
* print(f[2]); // Prints "30.0"
*
*
*/
p5.Vector.prototype.array = function () {
return [this.x || 0, this.y || 0, this.z || 0];
};
/**
* Equality check against a p5.Vector
*
* @method equals
* @param {Number|p5.Vector|Array} [x] the x component of the vector or a
* p5.Vector or an Array
* @param {Number} [y] the y component of the vector
* @param {Number} [z] the z component of the vector
* @return {Boolean} whether the vectors are equals
* @example
*
* v1 = createVector(5,10,20);
* v2 = createVector(5,10,20);
* v3 = createVector(13,10,19);
*
* print(v1.equals(v2.x,v2.y,v2.z)); // true
* print(v1.equals(v3.x,v3.y,v3.z)); // false
*
*
*
* var v1 = createVector(10.0, 20.0, 30.0);
* var v2 = createVector(10.0, 20.0, 30.0);
* var v3 = createVector(0.0, 0.0, 0.0);
* print (v1.equals(v2)) // true
* print (v1.equals(v3)) // false
*
*
*/
p5.Vector.prototype.equals = function (x, y, z) {
var a, b, c;
if (x instanceof p5.Vector) {
a = x.x || 0;
b = x.y || 0;
c = x.z || 0;
} else if (x instanceof Array) {
a = x[0] || 0;
b = x[1] || 0;
c = x[2] || 0;
} else {
a = x || 0;
b = y || 0;
c = z || 0;
}
return this.x === a && this.y === b && this.z === c;
};
// Static Methods
/**
* Make a new 2D unit vector from an angle
*
* @method fromAngle
* @static
* @param {Number} angle the desired angle
* @return {p5.Vector} the new p5.Vector object
* @example
*
*
* function draw() {
* background (200);
*
* // Create a variable, proportional to the mouseX,
* // varying from 0-360, to represent an angle in degrees.
* angleMode(DEGREES);
* var myDegrees = map(mouseX, 0,width, 0,360);
*
* // Display that variable in an onscreen text.
* // (Note the nfc() function to truncate additional decimal places,
* // and the "\xB0" character for the degree symbol.)
* var readout = "angle = " + nfc(myDegrees,1,1) + "\xB0"
* noStroke();
* fill (0);
* text (readout, 5, 15);
*
* // Create a p5.Vector using the fromAngle function,
* // and extract its x and y components.
* var v = p5.Vector.fromAngle(radians(myDegrees));
* var vx = v.x;
* var vy = v.y;
*
* push();
* translate (width/2, height/2);
* noFill();
* stroke (150);
* line (0,0, 30,0);
* stroke (0);
* line (0,0, 30*vx, 30*vy);
* pop()
* }
*
*
*/
p5.Vector.fromAngle = function(angle) {
if (this.p5) {
if (this.p5._angleMode === constants.DEGREES) {
angle = polarGeometry.degreesToRadians(angle);
}
}
if (this.p5) {
return new p5.Vector(this.p5,[Math.cos(angle),Math.sin(angle),0]);
} else {
return new p5.Vector(Math.cos(angle),Math.sin(angle),0);
}
};
/**
* Make a new 2D unit vector from a random angle
*
* @method random2D
* @static
* @return {p5.Vector} the new p5.Vector object
* @example
*
*
* var v = p5.Vector.random2D();
* // May make v's attributes something like:
* // [0.61554617, -0.51195765, 0.0] or
* // [-0.4695841, -0.14366731, 0.0] or
* // [0.6091097, -0.22805278, 0.0]
*
*
*/
p5.Vector.random2D = function () {
var angle;
// A lot of nonsense to determine if we know about a
// p5 sketch and whether we should make a random angle in degrees or radians
if (this.p5) {
if (this.p5._angleMode === constants.DEGREES) {
angle = this.p5.random(360);
} else {
angle = this.p5.random(constants.TWO_PI);
}
} else {
angle = Math.random()*Math.PI*2;
}
return this.fromAngle(angle);
};
/**
* Make a new random 3D unit vector.
*
* @method random3D
* @static
* @return {p5.Vector} the new p5.Vector object
* @example
*
*
* var v = p5.Vector.random3D();
* // May make v's attributes something like:
* // [0.61554617, -0.51195765, 0.599168] or
* // [-0.4695841, -0.14366731, -0.8711202] or
* // [0.6091097, -0.22805278, -0.7595902]
*
*
*/
p5.Vector.random3D = function () {
var angle,vz;
// If we know about p5
if (this.p5) {
angle = this.p5.random(0,constants.TWO_PI);
vz = this.p5.random(-1,1);
} else {
angle = Math.random()*Math.PI*2;
vz = Math.random()*2-1;
}
var vx = Math.sqrt(1-vz*vz)*Math.cos(angle);
var vy = Math.sqrt(1-vz*vz)*Math.sin(angle);
if (this.p5) {
return new p5.Vector(this.p5,[vx,vy,vz]);
} else {
return new p5.Vector(vx,vy,vz);
}
};
/**
* Adds two vectors together and returns a new one.
*
* @static
* @param {p5.Vector} v1 a p5.Vector to add
* @param {p5.Vector} v2 a p5.Vector to add
* @param {p5.Vector} target if undefined a new vector will be created
* @return {p5.Vector} the resulting p5.Vector
*
*/
p5.Vector.add = function (v1, v2, target) {
if (!target) {
target = v1.copy();
} else {
target.set(v1);
}
target.add(v2);
return target;
};
/**
* Subtracts one p5.Vector from another and returns a new one. The second
* vector (v2) is subtracted from the first (v1), resulting in v1-v2.
*
* @static
* @param {p5.Vector} v1 a p5.Vector to subtract from
* @param {p5.Vector} v2 a p5.Vector to subtract
* @param {p5.Vector} target if undefined a new vector will be created
* @return {p5.Vector} the resulting p5.Vector
*/
p5.Vector.sub = function (v1, v2, target) {
if (!target) {
target = v1.copy();
} else {
target.set(v1);
}
target.sub(v2);
return target;
};
/**
* Multiplies a vector by a scalar and returns a new vector.
*
* @static
* @param {p5.Vector} v the p5.Vector to multiply
* @param {Number} n the scalar
* @param {p5.Vector} target if undefined a new vector will be created
* @return {p5.Vector} the resulting new p5.Vector
*/
p5.Vector.mult = function (v, n, target) {
if (!target) {
target = v.copy();
} else {
target.set(v);
}
target.mult(n);
return target;
};
/**
* Divides a vector by a scalar and returns a new vector.
*
* @static
* @param {p5.Vector} v the p5.Vector to divide
* @param {Number} n the scalar
* @param {p5.Vector} target if undefined a new vector will be created
* @return {p5.Vector} the resulting new p5.Vector
*/
p5.Vector.div = function (v, n, target) {
if (!target) {
target = v.copy();
} else {
target.set(v);
}
target.div(n);
return target;
};
/**
* Calculates the dot product of two vectors.
*
* @static
* @param {p5.Vector} v1 the first p5.Vector
* @param {p5.Vector} v2 the second p5.Vector
* @return {Number} the dot product
*/
p5.Vector.dot = function (v1, v2) {
return v1.dot(v2);
};
/**
* Calculates the cross product of two vectors.
*
* @static
* @param {p5.Vector} v1 the first p5.Vector
* @param {p5.Vector} v2 the second p5.Vector
* @return {Number} the cross product
*/
p5.Vector.cross = function (v1, v2) {
return v1.cross(v2);
};
/**
* Calculates the Euclidean distance between two points (considering a
* point as a vector object).
*
* @static
* @param {p5.Vector} v1 the first p5.Vector
* @param {p5.Vector} v2 the second p5.Vector
* @return {Number} the distance
*/
p5.Vector.dist = function (v1,v2) {
return v1.dist(v2);
};
/**
* Linear interpolate a vector to another vector and return the result as a
* new vector.
*
* @static
* @param {p5.Vector} v1 a starting p5.Vector
* @param {p5.Vector} v2 the p5.Vector to lerp to
* @param {Number} the amount of interpolation; some value between 0.0
* (old vector) and 1.0 (new vector). 0.1 is very near
* the new vector. 0.5 is halfway in between.
*/
p5.Vector.lerp = function (v1, v2, amt, target) {
if (!target) {
target = v1.copy();
} else {
target.set(v1);
}
target.lerp(v2, amt);
return target;
};
/**
* Calculates and returns the angle (in radians) between two vectors.
* @method angleBetween
* @static
* @param {p5.Vector} v1 the x, y, and z components of a p5.Vector
* @param {p5.Vector} v2 the x, y, and z components of a p5.Vector
* @return {Number} the angle between (in radians)
* @example
*
*
* var v1 = createVector(1, 0, 0);
* var v2 = createVector(0, 1, 0);
*
* var angle = p5.Vector.angleBetween(v1, v2);
* // angle is PI/2
*
*
*/
p5.Vector.angleBetween = function (v1, v2) {
var angle = Math.acos(v1.dot(v2) / (v1.mag() * v2.mag()));
if (this.p5) {
if (this.p5._angleMode === constants.DEGREES) {
angle = polarGeometry.radiansToDegrees(angle);
}
}
return angle;
};
module.exports = p5.Vector;
},{"../core/constants":15,"../core/core":16,"./polargeometry":45}],45:[function(require,module,exports){
module.exports = {
degreesToRadians: function(x) {
return 2 * Math.PI * x / 360;
},
radiansToDegrees: function(x) {
return 360 * x / (2 * Math.PI);
}
};
},{}],46:[function(require,module,exports){
/**
* @module Math
* @submodule Random
* @for p5
* @requires core
*/
'use strict';
var p5 = require('../core/core');
var seeded = false;
// Linear Congruential Generator
// Variant of a Lehman Generator
var lcg = (function() {
// Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
// m is basically chosen to be large (as it is the max period)
// and for its relationships to a and c
var m = 4294967296,
// a - 1 should be divisible by m's prime factors
a = 1664525,
// c and m should be co-prime
c = 1013904223,
seed, z;
return {
setSeed : function(val) {
// pick a random seed if val is undefined or null
// the >>> 0 casts the seed to an unsigned 32-bit integer
z = seed = (val == null ? Math.random() * m : val) >>> 0;
},
getSeed : function() {
return seed;
},
rand : function() {
// define the recurrence relationship
z = (a * z + c) % m;
// return a float in [0, 1)
// if z = m then z / m = 0 therefore (z % m) / m < 1 always
return z / m;
}
};
}());
/**
* Sets the seed value for random().
*
* By default, random() produces different results each time the program
* is run. Set the seed parameter to a constant to return the same
* pseudo-random numbers each time the software is run.
*
* @method randomSeed
* @param {Number} seed the seed value
* @example
*
*
* randomSeed(99);
* for (var i=0; i < 100; i++) {
* var r = random(0, 255);
* stroke(r);
* line(i, 0, i, 100);
* }
*
*
*/
p5.prototype.randomSeed = function(seed) {
lcg.setSeed(seed);
seeded = true;
};
/**
* Return a random number.
*
* Takes either 0, 1 or 2 arguments.
* If no argument is given, returns a random number between 0 and 1.
* If one argument is given, returns a random number between 0 and the number.
* If two arguments are given, returns a random number between them,
* inclusive.
*
* @method random
* @param {Number} min the lower bound
* @param {Number} max the upper bound
* @return {Number} the random number
* @example
*
*
* for (var i = 0; i < 100; i++) {
* var r = random(50);
* stroke(r*5);
* line(50, i, 50+r, i);
* }
*
*
*
*
* for (var i = 0; i < 100; i++) {
* var r = random(-50, 50);
* line(50,i,50+r,i);
* }
*
*
*
*
* // Get a random element from an array
* var words = [ "apple", "bear", "cat", "dog" ];
* var index = floor(random(words.length)); // Convert to integer
* text(words[index],10,50); // Displays one of the four words
*
*
*/
p5.prototype.random = function (min, max) {
var rand;
if (seeded) {
rand = lcg.rand();
} else {
rand = Math.random();
}
if (arguments.length === 0) {
return rand;
} else
if (arguments.length === 1) {
return rand * min;
} else {
if (min > max) {
var tmp = min;
min = max;
max = tmp;
}
return rand * (max-min) + min;
}
};
/**
*
* Returns a random number fitting a Gaussian, or
* normal, distribution. There is theoretically no minimum or maximum
* value that randomGaussian() might return. Rather, there is
* just a very low probability that values far from the mean will be
* returned; and a higher probability that numbers near the mean will
* be returned.
* Takes either 0, 1 or 2 arguments.
* If no args, returns a mean of 0 and standard deviation of 1
* If one arg, that arg is the mean (standard deviation is 1)
* If two args, first is mean, second is standard deviation
*
* @method randomGaussian
* @param {Number} mean the mean
* @param {Number} sd the standard deviation
* @return {Number} the random number
* @example
*
* for (var y = 0; y < 100; y++) {
* var x = randomGaussian(50,15);
* line(50, y, x, y);
*}
*
*
*
*
*var distribution = new Array(360);
*
*function setup() {
* createCanvas(100, 100);
* for (var i = 0; i < distribution.length; i++) {
* distribution[i] = floor(randomGaussian(0,15));
* }
*}
*
*function draw() {
* background(204);
*
* translate(width/2, width/2);
*
* for (var i = 0; i < distribution.length; i++) {
* rotate(TWO_PI/distribution.length);
* stroke(0);
* var dist = abs(distribution[i]);
* line(0, 0, dist, 0);
* }
*}
*
*
*/
var y2;
var previous = false;
p5.prototype.randomGaussian = function(mean, sd) {
var y1,x1,x2,w;
if (previous) {
y1 = y2;
previous = false;
} else {
do {
x1 = this.random(2) - 1;
x2 = this.random(2) - 1;
w = x1 * x1 + x2 * x2;
} while (w >= 1);
w = Math.sqrt((-2 * Math.log(w))/w);
y1 = x1 * w;
y2 = x2 * w;
previous = true;
}
var m = mean || 0;
var s = sd || 1;
return y1*s + m;
};
module.exports = p5;
},{"../core/core":16}],47:[function(require,module,exports){
/**
* @module Math
* @submodule Trigonometry
* @for p5
* @requires core
* @requires polargeometry
* @requires constants
*/
'use strict';
var p5 = require('../core/core');
var polarGeometry = require('./polargeometry');
var constants = require('../core/constants');
p5.prototype._angleMode = constants.RADIANS;
/**
* The inverse of cos(), returns the arc cosine of a value. This function
* expects the values in the range of -1 to 1 and values are returned in
* the range 0 to PI (3.1415927).
*
* @method acos
* @param {Number} value the value whose arc cosine is to be returned
* @return {Number} the arc cosine of the given value
*
* @example
*
*
* var a = PI;
* var c = cos(a);
* var ac = acos(c);
* // Prints: "3.1415927 : -1.0 : 3.1415927"
* println(a + " : " + c + " : " + ac);
*
*
*
*
*
* var a = PI + PI/4.0;
* var c = cos(a);
* var ac = acos(c);
* // Prints: "3.926991 : -0.70710665 : 2.3561943"
* println(a + " : " + c + " : " + ac);
*
*
*/
p5.prototype.acos = function(ratio) {
if (this._angleMode === constants.RADIANS) {
return Math.acos(ratio);
} else {
return polarGeometry.radiansToDegrees(Math.acos(ratio));
}
};
/**
* The inverse of sin(), returns the arc sine of a value. This function
* expects the values in the range of -1 to 1 and values are returned
* in the range -PI/2 to PI/2.
*
* @method asin
* @param {Number} value the value whose arc sine is to be returned
* @return {Number} the arc sine of the given value
*
* @example
*
*
* var a = PI + PI/3;
* var s = sin(a);
* var as = asin(s);
* // Prints: "1.0471976 : 0.86602545 : 1.0471976"
* println(a + " : " + s + " : " + as);
*
*
*
*
*
* var a = PI + PI/3.0;
* var s = sin(a);
* var as = asin(s);
* // Prints: "4.1887903 : -0.86602545 : -1.0471976"
* println(a + " : " + s + " : " + as);
*
*
*
*/
p5.prototype.asin = function(ratio) {
if (this._angleMode === constants.RADIANS) {
return Math.asin(ratio);
} else {
return polarGeometry.radiansToDegrees(Math.asin(ratio));
}
};
/**
* The inverse of tan(), returns the arc tangent of a value. This function
* expects the values in the range of -Infinity to Infinity (exclusive) and
* values are returned in the range -PI/2 to PI/2.
*
* @method atan
* @param {Number} value the value whose arc tangent is to be returned
* @return {Number} the arc tangent of the given value
*
* @example
*
*
* var a = PI + PI/3;
* var t = tan(a);
* var at = atan(t);
* // Prints: "1.0471976 : 1.7320509 : 1.0471976"
* println(a + " : " + t + " : " + at);
*
*
*
*
*
* var a = PI + PI/3.0;
* var t = tan(a);
* var at = atan(t);
* // Prints: "4.1887903 : 1.7320513 : 1.0471977"
* println(a + " : " + t + " : " + at);
*
*
*
*/
p5.prototype.atan = function(ratio) {
if (this._angleMode === constants.RADIANS) {
return Math.atan(ratio);
} else {
return polarGeometry.radiansToDegrees(Math.atan(ratio));
}
};
/**
* Calculates the angle (in radians) from a specified point to the coordinate
* origin as measured from the positive x-axis. Values are returned as a
* float in the range from PI to -PI. The atan2() function is most often used
* for orienting geometry to the position of the cursor. Note: The
* y-coordinate of the point is the first parameter, and the x-coordinate is
* the second parameter, due the the structure of calculating the tangent.
*
* @method atan2
* @param {Number} y y-coordinate of the point
* @param {Number} x x-coordinate of the point
* @return {Number} the arc tangent of the given point
*
* @example
*
*
* function draw() {
* background(204);
* translate(width/2, height/2);
* var a = atan2(mouseY-height/2, mouseX-width/2);
* rotate(a);
* rect(-30, -5, 60, 10);
* }
*
*
*/
p5.prototype.atan2 = function (y, x) {
if (this._angleMode === constants.RADIANS) {
return Math.atan2(y, x);
} else {
return polarGeometry.radiansToDegrees(Math.atan2(y, x));
}
};
/**
* Calculates the cosine of an angle. This function takes into account the
* current angleMode. Values are returned in the range -1 to 1.
*
* @method cos
* @param {Number} angle the angle
* @return {Number} the cosine of the angle
*
* @example
*
*
* var a = 0.0;
* var inc = TWO_PI/25.0;
* for (var i = 0; i < 25; i++) {
* line(i*4, 50, i*4, 50+cos(a)*40.0);
* a = a + inc;
* }
*
*
*
*/
p5.prototype.cos = function(angle) {
if (this._angleMode === constants.RADIANS) {
return Math.cos(angle);
} else {
return Math.cos(this.radians(angle));
}
};
/**
* Calculates the sine of an angle. This function takes into account the
* current angleMode. Values are returned in the range -1 to 1.
*
* @method sin
* @param {Number} angle the angle
* @return {Number} the sine of the angle
*
* @example
*
*
* var a = 0.0;
* var inc = TWO_PI/25.0;
* for (var i = 0; i < 25; i++) {
* line(i*4, 50, i*4, 50+sin(a)*40.0);
* a = a + inc;
* }
*
*
*/
p5.prototype.sin = function(angle) {
if (this._angleMode === constants.RADIANS) {
return Math.sin(angle);
} else {
return Math.sin(this.radians(angle));
}
};
/**
* Calculates the tangent of an angle. This function takes into account
* the current angleMode. Values are returned in the range -1 to 1.
*
* @method tan
* @param {Number} angle the angle
* @return {Number} the tangent of the angle
*
* @example
*
*
* var a = 0.0;
* var inc = TWO_PI/50.0;
* for (var i = 0; i < 100; i = i+2) {
* line(i, 50, i, 50+tan(a)*2.0);
* a = a + inc;
* }
*
*
*
*/
p5.prototype.tan = function(angle) {
if (this._angleMode === constants.RADIANS) {
return Math.tan(angle);
} else {
return Math.tan(this.radians(angle));
}
};
/**
* Converts a radian measurement to its corresponding value in degrees.
* Radians and degrees are two ways of measuring the same thing. There are
* 360 degrees in a circle and 2*PI radians in a circle. For example,
* 90° = PI/2 = 1.5707964.
*
* @method degrees
* @param {Number} radians the radians value to convert to degrees
* @return {Number} the converted angle
*
*
* @example
*
*
* var rad = PI/4;
* var deg = degrees(rad);
* println(rad + " radians is " + deg + " degrees");
* // Prints: 45 degrees is 0.7853981633974483 radians
*
*
*
*/
p5.prototype.degrees = function(angle) {
return polarGeometry.radiansToDegrees(angle);
};
/**
* Converts a degree measurement to its corresponding value in radians.
* Radians and degrees are two ways of measuring the same thing. There are
* 360 degrees in a circle and 2*PI radians in a circle. For example,
* 90° = PI/2 = 1.5707964.
*
* @method radians
* @param {Number} degrees the degree value to convert to radians
* @return {Number} the converted angle
*
* @example
*
*
* var deg = 45.0;
* var rad = radians(deg);
* println(deg + " degrees is " + rad + " radians");
* // Prints: 45 degrees is 0.7853981633974483 radians
*
*
*/
p5.prototype.radians = function(angle) {
return polarGeometry.degreesToRadians(angle);
};
/**
* Sets the current mode of p5 to given mode. Default mode is RADIANS.
*
* @method angleMode
* @param {Number/Constant} mode either RADIANS or DEGREES
*
* @example
*
*
* function draw(){
* background(204);
* angleMode(DEGREES); // Change the mode to DEGREES
* var a = atan2(mouseY-height/2, mouseX-width/2);
* translate(width/2, height/2);
* push();
* rotate(a);
* rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees
* pop();
* angleMode(RADIANS); // Change the mode to RADIANS
* rotate(a); // var a stays the same
* rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians
* }
*
*
*
*/
p5.prototype.angleMode = function(mode) {
if (mode === constants.DEGREES || mode === constants.RADIANS) {
this._angleMode = mode;
}
};
module.exports = p5;
},{"../core/constants":15,"../core/core":16,"./polargeometry":45}],48:[function(require,module,exports){
/**
* @module Typography
* @submodule Attributes
* @for p5
* @requires core
* @requires constants
*/
'use strict';
var p5 = require('../core/core');
var constants = require('../core/constants');
p5.prototype._textSize = 12;
p5.prototype._textLeading = 15;
p5.prototype._textFont = 'sans-serif';
p5.prototype._textStyle = constants.NORMAL;
p5.prototype._textAscent = null;
p5.prototype._textDescent = null;
/**
* Sets the current alignment for drawing text. The parameters LEFT, CENTER,
* and RIGHT set the display characteristics of the letters in relation to
* the values for the x and y parameters of the text() function.
*
* @method textAlign
* @param {Number/Constant} h horizontal alignment, either LEFT,
* CENTER, or RIGHT
* @param {Number/Constant} v vertical alignment, either TOP,
* BOTTOM, CENTER, or BASELINE
* @return {Number}
* @example
*
*
* textSize(16);
* textAlign(RIGHT);
* text("ABCD", 50, 30);
* textAlign(CENTER);
* text("EFGH", 50, 50);
* textAlign(LEFT);
* text("IJKL", 50, 70);
*
*
*/
p5.prototype.textAlign = function(h, v) {
return this._graphics.textAlign(h,v);
};
/**
* Sets/gets the spacing between lines of text in units of pixels. This
* setting will be used in all subsequent calls to the text() function.
*
* @method textLeading
* @param {Number} l the size in pixels for spacing between lines
* @return {Object|Number}
* @example
*
*
* // Text to display. The "\n" is a "new line" character
* lines = "L1\nL2\nL3";
* textSize(12);
* fill(0); // Set fill to black
*
* textLeading(10); // Set leading to 10
* text(lines, 10, 25);
*
* textLeading(20); // Set leading to 20
* text(lines, 40, 25);
*
* textLeading(30); // Set leading to 30
* text(lines, 70, 25);
*
*
*/
p5.prototype.textLeading = function(l) {
if (arguments.length) {
this._setProperty('_textLeading', l);
return this;
}
return this._textLeading;
};
/**
* Sets/gets the current font size. This size will be used in all subsequent
* calls to the text() function. Font size is measured in units of pixels.
*
* @method textSize
* @param {Number} s the size of the letters in units of pixels
* @return {Object|Number}
* @example
*
*
* textSize(12);
* text("Font Size 12", 10, 30);
* textSize(14);
* text("Font Size 14", 10, 60);
* textSize(16);
* text("Font Size 16", 10, 90);
*
*
*/
p5.prototype.textSize = function(s) {
if (arguments.length) {
this._setProperty('_textSize', s);
this._setProperty('_textLeading', s * constants._DEFAULT_LEADMULT);
return this._graphics._applyTextProperties();
}
return this._textSize;
};
/**
* Sets/gets the style of the text to NORMAL, ITALIC, or BOLD. Note this is
* overridden by CSS styling.
* (Style only apply to system font, for custom fonts, please load styled
* fonts instead.)
*
* @method textStyle
* @param {Number/Constant} s styling for text, either NORMAL,
* ITALIC, or BOLD
* @return {Object|String}
* @example
*
*
* fill(0);
* strokeWeight(0);
* textSize(12);
* textStyle(NORMAL);
* text("Font Style Normal", 10, 30);
* textStyle(ITALIC);
* text("Font Style Italic", 10, 60);
* textStyle(BOLD);
* text("Font Style Bold", 10, 90);
*
*
*/
p5.prototype.textStyle = function(s) {
if (arguments.length) {
if (s === constants.NORMAL ||
s === constants.ITALIC ||
s === constants.BOLD) {
this._setProperty('_textStyle', s);
}
return this._graphics._applyTextProperties();
}
return this._textStyle;
};
/**
* Calculates and returns the width of any character or text string.
*
* @method textWidth
* @param {String} s the String of characters to measure
* @return {Number}
* @example
*
*
* textSize(28);
*
* var c = 'P';
* var cw = textWidth(c);
* text(c, 0, 40);
* line(cw, 0, cw, 50);
*
* var s = "p5.js";
* var sw = textWidth(s);
* text(s, 0, 85);
* line(sw, 50, sw, 100);
*
*
*/
p5.prototype.textWidth = function(s) {
return this._graphics.textWidth(s);
};
/**
* Returns ascent of the current font at its current size.
* @return {Number}
* @example
*
*
* var base = height * 0.75;
* var scalar = 0.8; // Different for each font
*
* textSize(32); // Set initial text size
* var a = textAscent() * scalar; // Calc ascent
* line(0, base-a, width, base-a);
* text("dp", 0, base); // Draw text on baseline
*
* textSize(64); // Increase text size
* a = textAscent() * scalar; // Recalc ascent
* line(40, base-a, width, base-a);
* text("dp", 40, base); // Draw text on baseline
*
*
*/
p5.prototype.textAscent = function() {
if (this._textAscent === null) {
this._updateTextMetrics();
}
return this._textAscent;
};
/*p5.prototype.fontMetrics = function(font, text, x, y, fontSize) {
var xMins = [], yMins = [], xMaxs= [], yMaxs = [], p5 = this;
//font = font || this._textFont;
fontSize = fontSize || p5._textSize;
font.forEachGlyph(text, x, y, fontSize,
{}, function(glyph, gX, gY, gFontSize) {
var gm = glyph.getMetrics();
gX = gX !== undefined ? gX : 0;
gY = gY !== undefined ? gY : 0;
fontSize = fontSize !== undefined ? fontSize : 24;
var scale = 1 / font.unitsPerEm * fontSize;
p5.noFill();
p5.rectMode(p5.CORNERS);
p5.rect(gX + (gm.xMin * scale), gY + (-gm.yMin * scale),
gX + (gm.xMax * scale), gY + (-gm.yMax * scale));
p5.rectMode(p5.CORNER);
});
return { // metrics
xMin: Math.min.apply(null, xMins),
yMin: Math.min.apply(null, yMins),
xMax: Math.max.apply(null, xMaxs),
yMax: Math.max.apply(null, yMaxs)
};
};*/
/**
* Returns descent of the current font at its current size.
* @return {Number}
* @example
*
*
* var base = height * 0.75;
* var scalar = 0.8; // Different for each font
*
* textSize(32); // Set initial text size
* var a = textDescent() * scalar; // Calc ascent
* line(0, base+a, width, base+a);
* text("dp", 0, base); // Draw text on baseline
*
* textSize(64); // Increase text size
* a = textDescent() * scalar; // Recalc ascent
* line(40, base+a, width, base+a);
* text("dp", 40, base); // Draw text on baseline
*
*
*/
p5.prototype.textDescent = function() {
if (this._textDescent === null) {
this._updateTextMetrics();
}
return this._textDescent;
};
/**
* Helper fxn to check font type (system or otf)
*/
p5.prototype._isOpenType = function(f) {
f = f || this._textFont;
return (typeof f === 'object' && f.font && f.font.supported);
};
/**
* Helper fxn to measure ascent and descent.
*/
p5.prototype._updateTextMetrics = function() {
if (this._isOpenType()) {
this._setProperty('_textAscent', this._textFont._textAscent());
this._setProperty('_textDescent', this._textFont._textDescent());
return this;
}
// Adapted from http://stackoverflow.com/a/25355178
var text = document.createElement('span');
text.style.fontFamily = this._textFont;
text.style.fontSize = this._textSize + 'px';
text.innerHTML = 'ABCjgq|';
var block = document.createElement('div');
block.style.display = 'inline-block';
block.style.width = '1px';
block.style.height = '0px';
var container = document.createElement('div');
container.appendChild(text);
container.appendChild(block);
container.style.height = '0px';
container.style.overflow = 'hidden';
document.body.appendChild(container);
block.style.verticalAlign = 'baseline';
var blockOffset = this._calculateOffset(block);
var textOffset = this._calculateOffset(text);
var ascent = blockOffset[1] - textOffset[1];
block.style.verticalAlign = 'bottom';
blockOffset = this._calculateOffset(block);
textOffset = this._calculateOffset(text);
var height = blockOffset[1] - textOffset[1];
var descent = height - ascent;
document.body.removeChild(container);
this._setProperty('_textAscent', ascent);
this._setProperty('_textDescent', descent);
return this;
};
/**
* Helper fxn to measure ascent and descent.
* Adapted from http://stackoverflow.com/a/25355178
*/
p5.prototype._calculateOffset = function(object) {
var currentLeft = 0,
currentTop = 0;
if (object.offsetParent) {
do {
currentLeft += object.offsetLeft;
currentTop += object.offsetTop;
} while (object = object.offsetParent);
} else {
currentLeft += object.offsetLeft;
currentTop += object.offsetTop;
}
return [currentLeft, currentTop];
};
module.exports = p5;
},{"../core/constants":15,"../core/core":16}],49:[function(require,module,exports){
/**
* @module Typography
* @submodule Loading & Displaying
* @for p5
* @requires core
*/
'use strict';
var p5 = require('../core/core');
var constants = require('../core/constants');
require('../core/error_helpers');
/**
* Draws text to the screen. Displays the information specified in the first
* parameter on the screen in the position specified by the additional
* parameters. A default font will be used unless a font is set with the
* textFont() function and a default size will be used unless a font is set
* with textSize(). Change the color of the text with the fill() function.
* Change the outline of the text with the stroke() and strokeWeight()
* functions.
*
* The text displays in relation to the textAlign() function, which gives the
* option to draw to the left, right, and center of the coordinates.
*
* The x2 and y2 parameters define a rectangular area to display within and
* may only be used with string data. When these parameters are specified,
* they are interpreted based on the current rectMode() setting. Text that
* does not fit completely within the rectangle specified will not be drawn
* to the screen.
*
* @method text
* @param {String} str the alphanumeric symbols to be displayed
* @param {Number} x x-coordinate of text
* @param {Number} y y-coordinate of text
* @param {Number} x2 by default, the width of the text box,
* see rectMode() for more info
* @param {Number} y2 by default, the height of the text box,
* see rectMode() for more info
* @return {Object} this
* @example
*
*
* textSize(32);
* text("word", 10, 30);
* fill(0, 102, 153);
* text("word", 10, 60);
* fill(0, 102, 153, 51);
* text("word", 10, 90);
*
*
*
*
* s = "The quick brown fox jumped over the lazy dog.";
* fill(50);
* text(s, 10, 10, 70, 80); // Text wraps within text box
*
*
*/
p5.prototype.text = function(str, x, y, maxWidth, maxHeight) {
this._validateParameters(
'text',
arguments,
[
['*', 'Number', 'Number'],
['*', 'Number', 'Number', 'Number', 'Number']
]
);
return (!(this._doFill || this._doStroke)) ? this :
this._graphics.text.apply(this._graphics, arguments);
};
/**
* Sets the current font that will be drawn with the text() function.
*
* @method textFont
* @param {Object|String} f a font loaded via loadFont(), or a String
* representing a browser-based dfault font.
* @return {Object} this
* @example
*
*
* fill(0);
* textSize(12);
* textFont("Georgia");
* text("Georgia", 12, 30);
* textFont("Helvetica");
* text("Helvetica", 12, 60);
*
*
*
*
* var fontRegular, fontItalic, fontBold;
* function preload() {
* fontRegular = loadFont("assets/Regular.otf");
* fontItalic = loadFont("assets/Italic.ttf");
* fontBold = loadFont("assets/Bold.ttf");
* }
* function setup() {
* background(210);
* fill(0).strokeWeight(0).textSize(10);
* textFont(fontRegular);
* text("Font Style Normal", 10, 30);
* textFont(fontItalic);
* text("Font Style Italic", 10, 50);
* textFont(fontBold);
* text("Font Style Bold", 10, 70);
* }
*
*
*/
p5.prototype.textFont = function(theFont, theSize) {
if (arguments.length) {
if (!theFont) {
throw Error('null font passed to textFont');
}
this._setProperty('_textFont', theFont);
if (theSize) {
this._setProperty('_textSize', theSize);
this._setProperty('_textLeading',
theSize * constants._DEFAULT_LEADMULT);
}
return this._graphics._applyTextProperties();
}
return this;
};
module.exports = p5;
},{"../core/constants":15,"../core/core":16,"../core/error_helpers":19}],50:[function(require,module,exports){
/**
* This module defines the p5.Font class and P5 methods for
* drawing text to the main display canvas.
* @module Typography
* @submodule Font
* @requires core
* @requires constants
*/
/*
* TODO:
* -- var fonts = loadFont([]); **
* -- PFont functions:
* textBounds() exists
* glyphPaths -> object or array?
* PFont.list()
* -- Integrating p5.dom (later)
* -- alignment: justified
* -- kerning
* -- truncation
* -- drop-caps
*/
'use strict';
var p5 = require('../core/core');
var constants = require('../core/constants');
/**
* Base class for font handling
* @class p5.Font
* @constructor
* @param {Object} [pInst] pointer to p5 instance
*/
p5.Font = function(p) {
this.parent = p;
this.cache = {};
/**
* Underlying opentype font implementation
* @property font
*/
this.font = undefined;
};
/**
* Returns the set of opentype glyphs for the supplied string.
*
* Note that there is not a strict one-to-one mapping between characters
* and glyphs, so the list of returned glyphs can be larger or smaller
* than the length of the given string.
*
* @param {String} str the string to be converted
* @return {array} the opentype glyphs
*/
p5.Font.prototype._getGlyphs = function(str) {
return this.font.stringToGlyphs(str);
};
/**
* Returns an opentype path for the supplied string and position.
*
* @param {String} line a line of text
* @param {Number} x x-position
* @param {Number} y y-position
* @param {Object} options opentype options (optional)
* @return {Object} the opentype path
*/
p5.Font.prototype._getPath = function(line, x, y, options) {
var p = this.parent, ctx = p._graphics.drawingContext,
pos = this._handleAlignment(p, ctx, line, x, y);
return this.font.getPath(line, pos.x, pos.y, p._textSize, options);
};
/*
* Creates an SVG-formatted path-data string
* (See http://www.w3.org/TR/SVG/paths.html#PathData)
* from the given opentype path or string/position
*
* @param {Object} path an opentype path, OR the following:
*
* @param {String} line a line of text
* @param {Number} x x-position
* @param {Number} y y-position
* @param {Object} options opentype options (optional), set options.decimals
* to set the decimal precision of the path-data
*
* @return {Object} this p5.Font object
*/
p5.Font.prototype._getPathData = function(line, x, y, options) {
var decimals = 3;
// create path from string/position
if (typeof line === 'string' && arguments.length > 2) {
line = this._getPath(line, x, y, options);
}
// handle options specified in 2nd arg
else if (typeof x === 'object') {
options = x;
}
// handle svg arguments
if (options && typeof options.decimals === 'number') {
decimals = options.decimals;
}
return line.toPathData(decimals);
};
/*
* Creates an SVG element, as a string, from the
* from the given opentype path or string/position
*
* @param {Object} path an opentype path, OR the following:
*
* @param {String} line a line of text
* @param {Number} x x-position
* @param {Number} y y-position
* @param {Object} options opentype options (optional), set options.decimals
* to set the decimal precision of the path-data in the element,
* options.fill to set the fill color for the element,
* options.stroke to set the stroke color for the element,
* options.strokeWidth to set the strokeWidth for the element.
*
* @return {Object} this p5.Font object
*/
p5.Font.prototype._getSVG = function(line, x, y, options) {
var decimals = 3;
// create path from string/position
if (typeof line === 'string' && arguments.length > 2) {
line = this._getPath(line, x, y, options);
}
// handle options specified in 2nd arg
else if (typeof x === 'object') {
options = x;
}
// handle svg arguments
if (options) {
if (typeof options.decimals === 'number') {
decimals = options.decimals;
}
if (typeof options.strokeWidth === 'number') {
line.strokeWidth = options.strokeWidth;
}
if (typeof options.fill !== undefined) {
line.fill = options.fill;
}
if (typeof options.stroke !== undefined) {
line.stroke = options.stroke;
}
}
return line.toSVG(decimals);
};
/*
* Renders an opentype path or string/position
* to the current graphics context
*
* @param {Object} path an opentype path, OR the following:
*
* @param {String} line a line of text
* @param {Number} x x-position
* @param {Number} y y-position
* @param {Object} options opentype options (optional)
*
* @return {Object} this p5.Font object
*/
p5.Font.prototype._renderPath = function(line, x, y, options) {
// /console.log('_renderPath', typeof line);
var pdata, p = this.parent, pg = p._graphics, ctx = pg.drawingContext;
if (typeof line === 'object' && line.commands) {
pdata = line.commands;
}
else {
//pos = handleAlignment(p, ctx, line, x, y);
pdata = this._getPath(line, x, y, p._textSize, options).commands;
}
ctx.beginPath();
for (var i = 0; i < pdata.length; i += 1) {
var cmd = pdata[i];
if (cmd.type === 'M') {
ctx.moveTo(cmd.x, cmd.y);
} else if (cmd.type === 'L') {
ctx.lineTo(cmd.x, cmd.y);
} else if (cmd.type === 'C') {
ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
} else if (cmd.type === 'Q') {
ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
} else if (cmd.type === 'Z') {
ctx.closePath();
}
}
// only draw stroke if manually set by user
if (p._doStroke && p._strokeSet) {
ctx.stroke();
}
if (p._doFill) {
// if fill hasn't been set by user, use default-text-fill
ctx.fillStyle = p._fillSet ? ctx.fillStyle:constants._DEFAULT_TEXT_FILL;
ctx.fill();
}
return this;
};
p5.Font.prototype._textWidth = function(str) {
if (str === ' ') { // special case for now
return this.font.charToGlyph(' ').advanceWidth * this._scale();
}
var bounds = this.textBounds(str);
return bounds.w + bounds.advance;
};
p5.Font.prototype._textAscent = function() {
var bounds = this.textBounds('ABCjgq|');
return Math.abs(bounds.y);
};
p5.Font.prototype._textDescent = function() {
var bounds = this.textBounds('ABCjgq|');
return bounds.h - Math.abs(bounds.y);
};
p5.Font.prototype._scale = function(fontSize) {
return (1 / this.font.unitsPerEm) * (fontSize || this.parent._textSize);
};
/**
* Returns a tight bounding box for the given custom text string using this
* font (currently only support single line)
*
* @method textBounds
* @param {String} line a line of text
* @param {Number} x x-position
* @param {Number} y y-position
* @param {Number} fontSize font size to use (optional)
* @param {Object} options opentype options (optional)
*
* @return {Object} a rectangle object with properties: x, y, w, h
*
* @example
*
*
* var font;
* var text = 'Lorem ipsum dolor sit amet.';
* function preload() {
* font = loadFont('./assets/fonts/Regular.otf');
* };
* function setup() {
* background(210);
* textFont(font);
* strokeWeight(1);
* textSize(12);
* var bbox = font.textBounds(text, 10, 30, 12);
* fill(255);
* stroke(0);
* rect(bbox.x, bbox.y, bbox.w, bbox.h);
* fill(0);
* strokeWeight(0);
* text(text, 10, 30);
* };
*
*
*/
p5.Font.prototype.textBounds = function(str, x, y, fontSize, options) {
x = x !== undefined ? x : 0;
y = y !== undefined ? y : 0;
fontSize = fontSize || this.parent._textSize;
//console.log('textBounds(',str, x, y, fontSize,')');
var result = this.cache[cacheKey('textBounds', str, x, y, fontSize)];
if (!result) {
// console.log('computing');
if (str !== ' ') {
var xCoords = [],
yCoords = [],
scale = this._scale(fontSize),
minX, minY, maxX, maxY;
this.font.forEachGlyph(str, x, y, fontSize, options,
function(glyph, gX, gY, gFontSize) {
if (glyph.name !== 'space') {
gX = gX !== undefined ? gX : 0;
gY = gY !== undefined ? gY : 0;
var gm = glyph.getMetrics();
xCoords.push(gX + (gm.xMin * scale));
yCoords.push(gY + (-gm.yMin * scale));
xCoords.push(gX + (gm.xMax * scale));
yCoords.push(gY + (-gm.yMax * scale));
}
});
minX = Math.min.apply(null, xCoords);
minY = Math.min.apply(null, yCoords);
maxX = Math.max.apply(null, xCoords);
maxY = Math.max.apply(null, yCoords);
result = {
x: minX,
y: minY,
h: maxY - minY,
w: maxX - minX,
advance: minX - x
};
}
else { // special case ' ' for now
var tw = this._textWidth(str);
result = {
x: x,
y: y,
h: 0,
w: tw,
advance: 0 // ?
};
}
this.cache[cacheKey('textBounds', str, x, y, fontSize)] = result;
}
//else { console.log('cache-hit'); }
return result;
};
p5.Font.prototype._drawPoints = function(str, tx, ty, options) { // remove?
var pdata, onCurvePts, offCurvePts, p = this.parent, scale = this._scale();
tx = tx !== undefined ? tx : 0;
ty = ty !== undefined ? ty : 0;
this.font.forEachGlyph(str, tx, ty, p._textSize, options,
function(glyph, x, y, fontSize) {
onCurvePts = [];
offCurvePts = [];
pdata = glyph.path.commands;
for (var i = 0; i < pdata.length; i += 1) {
var cmd = pdata[i];
if (cmd.x !== undefined) {
onCurvePts.push({ x: cmd.x, y: -cmd.y });
}
if (cmd.x1 !== undefined) {
offCurvePts.push({ x: cmd.x1, y: -cmd.y1 });
}
if (cmd.x2 !== undefined) {
offCurvePts.push({ x: cmd.x2, y: -cmd.y2 });
}
}
p.noStroke();
p.fill(0,0,255);
drawCircles(onCurvePts, x, y, scale);
p.fill(255,0,0);
drawCircles(offCurvePts, x, y, scale);
});
function drawCircles(l, x, y, scale) {
for (var j = 0; j < l.length; j++) {
p.ellipse(x + (l[j].x * scale), y + (l[j].y * scale), 3, 3);
}
}
};
p5.Font.prototype.list = function() {
// TODO
throw 'not yet implemented';
};
// helpers
p5.Font.prototype._handleAlignment = function(p, ctx, line, x, y) {
var textWidth = this._textWidth(line),
textAscent = this._textAscent(),
textDescent = this._textDescent(),
textHeight = textAscent + textDescent;
if (ctx.textAlign === constants.CENTER) {
x -= textWidth / 2;
} else if (ctx.textAlign === constants.RIGHT) {
x -= textWidth;
}
if (ctx.textBaseline === constants.TOP) {
y += textHeight;
} else if (ctx.textBaseline === constants._CTX_MIDDLE) {
y += textHeight / 2 - textDescent;
} else if (ctx.textBaseline === constants.BOTTOM) {
y -= textDescent;
}
return { x: x, y: y };
};
function cacheKey() {
var args = Array.prototype.slice.call(arguments),
i = args.length,
hash = '';
while (i--) {
hash += (args[i] === Object(args[i])) ?
JSON.stringify(args[i]) : args[i];
}
return hash;
}
module.exports = p5.Font;
},{"../core/constants":15,"../core/core":16}],51:[function(require,module,exports){
/**
* @module Data
* @submodule Array Functions
* @for p5
* @requires core
*/
'use strict';
var p5 = require('../core/core');
/**
* Adds a value to the end of an array. Extends the length of
* the array by one. Maps to Array.push().
*
* @method append
* @param {Array} array Array to append
* @param {any} value to be added to the Array
* @example
*
* function setup() {
*
* var myArray = new Array("Mango", "Apple", "Papaya")
* print(myArray) // ["Mango", "Apple", "Papaya"]
*
* append(myArray, "Peach")
* print(myArray) // ["Mango", "Apple", "Papaya", "Peach"]
*
* }
*
*/
p5.prototype.append = function(array, value) {
array.push(value);
return array;
};
/**
* Copies an array (or part of an array) to another array. The src array is
* copied to the dst array, beginning at the position specified by
* srcPosition and into the position specified by dstPosition. The number of
* elements to copy is determined by length. Note that copying values
* overwrites existing values in the destination array. To append values
* instead of overwriting them, use concat().
*
* The simplified version with only two arguments — arrayCopy(src, dst) —
* copies an entire array to another of the same size. It is equivalent to
* arrayCopy(src, 0, dst, 0, src.length).
*
* Using this function is far more efficient for copying array data than
* iterating through a for() loop and copying each element individually.
*
* @method arrayCopy
* @param {Array} src the source Array
* @param {Number} [srcPosition] starting position in the source Array
* @param {Array} dst the destination Array
* @param {Number} [dstPosition] starting position in the destination Array
* @param {Nimber} [length] number of Array elements to be copied
*
* @example
*
* function setup() {
*
* var src = new Array("A", "B", "C");
* var dst = new Array( 1 , 2 , 3 );
* var srcPosition = 1;
* var dstPosition = 0;
* var length = 2;
*
* print(src); // ["A", "B", "C"]
* print(dst); // [ 1 , 2 , 3 ]
*
* arrayCopy(src, srcPosition, dst, dstPosition, length);
* print(dst); // ["B", "C", 3]
*
* }
*
*/
p5.prototype.arrayCopy = function(
src,
srcPosition,
dst,
dstPosition,
length) {
// the index to begin splicing from dst array
var start,
end;
if (typeof length !== 'undefined') {
end = Math.min(length, src.length);
start = dstPosition;
src = src.slice(srcPosition, end + srcPosition);
} else {
if (typeof dst !== 'undefined') { // src, dst, length
// rename so we don't get confused
end = dst;
end = Math.min(end, src.length);
} else { // src, dst
end = src.length;
}
start = 0;
// rename so we don't get confused
dst = srcPosition;
src = src.slice(0, end);
}
// Since we are not returning the array and JavaScript is pass by reference
// we must modify the actual values of the array
// instead of reassigning arrays
Array.prototype.splice.apply(dst, [start, end].concat(src));
};
/**
* Concatenates two arrays, maps to Array.concat(). Does not modify the
* input arrays.
*
* @method concat
* @param {Array} a first Array to concatenate
* @param {Array} b second Array to concatenate
* @return {Array} concatenated array
*
* @example
*
* function setup() {
* var arr1 = new Array("A", "B", "C");
* var arr2 = new Array( 1 , 2 , 3 );
*
* print(arr1); // ["A","B","C"]
* print(arr2); // [1,2,3]
*
* var arr3 = concat(arr1, arr2);
*
* print(arr1); // ["A","B","C"]
* print(arr2); // [1,2,3]
* print(arr3); // ["A","B","C",1,2,3]
*
* }
*
*/
p5.prototype.concat = function(list0, list1) {
return list0.concat(list1);
};
/**
* Reverses the order of an array, maps to Array.reverse()
*
* @method reverse
* @param {Array} list Array to reverse
* @example
*
* function setup() {
* var myArray = new Array("A", "B", "C");
* print(myArray); // ["A","B","C"]
*
* reverse(myArray);
* print(myArray); // ["C","B","A"]
* }
*
*/
p5.prototype.reverse = function(list) {
return list.reverse();
};
/**
* Decreases an array by one element and returns the shortened array,
* maps to Array.pop().
*
* @method shorten
* @param {Array} list Array to shorten
* @return {Array} shortened Array
* @example
*
* function setup() {
* var myArray = new Array("A", "B", "C");
* print(myArray); // ["A","B","C"]
*
* var newArray = shorten(myArray);
* print(myArray); // ["A","B","C"]
* print(newArray); // ["A","B"]
* }
*
*/
p5.prototype.shorten = function(list) {
list.pop();
return list;
};
/**
* Randomizes the order of the elements of an array.
* Implements Fisher-Yates Shuffle Algorithm
* http://Bost.Ocks.org/mike/shuffle/
* http://en.Wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
*
* @method shuffle
* @param {Array} array Array to shuffle
* @param {Boolean} [bool] modify passed array
* @return {Array} shuffled Array
* @example
*
* function setup() {
* var regularArr = ['ABC', 'def', createVector(), TAU, Math.E];
* print(regularArr);
* shuffle(regularArr, true); // force modifications to passed array
* print(regularArr);
*
* // By default shuffle() returns a shuffled cloned array:
* var newArr = shuffle(regularArr);
* print(regularArr);
* print(newArr);
* }
*
*/
p5.prototype.shuffle = function(arr, bool) {
arr = bool || ArrayBuffer.isView(arr)? arr : arr.slice();
var rnd, tmp, idx = arr.length;
while (idx > 1) {
rnd = Math.random()*idx | 0;
tmp = arr[--idx];
arr[idx] = arr[rnd];
arr[rnd] = tmp;
}
return arr;
};
/**
* Sorts an array of numbers from smallest to largest, or puts an array of
* words in alphabetical order. The original array is not modified; a
* re-ordered array is returned. The count parameter states the number of
* elements to sort. For example, if there are 12 elements in an array and
* count is set to 5, only the first 5 elements in the array will be sorted.
*
* @method sort
* @param {Array} list Array to sort
* @param {Number} [count] number of elements to sort, starting from 0
*
* @example
*
* function setup() {
* var words = new Array("banana", "apple", "pear","lime");
* print(words); // ["banana", "apple", "pear", "lime"]
* var count = 4; // length of array
*
* sort(words, count);
* print(words); // ["apple", "banana", "lime", "pear"]
* }
*
*
* function setup() {
* var numbers = new Array(2,6,1,5,14,9,8,12);
* print(numbers); // [2,6,1,5,14,9,8,12]
* var count = 5; // Less than the length of the array
*
* sort(numbers, count);
* print(numbers); // [1,2,5,6,14,9,8,12]
* }
*
*/
p5.prototype.sort = function(list, count) {
var arr = count ? list.slice(0, Math.min(count, list.length)) : list;
var rest = count ? list.slice(Math.min(count, list.length)) : [];
if (typeof arr[0] === 'string') {
arr = arr.sort();
} else {
arr = arr.sort(function(a,b){return a-b;});
}
return arr.concat(rest);
};
/**
* Inserts a value or an array of values into an existing array. The first
* parameter specifies the initial array to be modified, and the second
* parameter defines the data to be inserted. The third parameter is an index
* value which specifies the array position from which to insert data.
* (Remember that array index numbering starts at zero, so the first position
* is 0, the second position is 1, and so on.)
*
* @method splice
* @param {Array} list Array to splice into
* @param {any} value value to be spliced in
* @param {Number} position in the array from which to insert data
*
* @example
*
* function setup() {
* var myArray = new Array(0,1,2,3,4);
* var insArray = new Array("A","B","C");
* print(myArray); // [0,1,2,3,4]
* print(insArray); // ["A","B","C"]
*
* splice(myArray, insArray, 3);
* print(myArray); // [0,1,2,"A","B","C",3,4]
* }
*
*/
p5.prototype.splice = function(list, value, index) {
// note that splice returns spliced elements and not an array
Array.prototype.splice.apply(list, [index, 0].concat(value));
return list;
};
/**
* Extracts an array of elements from an existing array. The list parameter
* defines the array from which the elements will be copied, and the start
* and count parameters specify which elements to extract. If no count is
* given, elements will be extracted from the start to the end of the array.
* When specifying the start, remember that the first array element is 0.
* This function does not change the source array.
*
* @method subset
* @param {Array} list Array to extract from
* @param {Number} start position to begin
* @param {Number} [count] number of values to extract
* @return {Array} Array of extracted elements
*
* @example
*
* function setup() {
* var myArray = new Array(1,2,3,4,5);
* print(myArray); // [1,2,3,4,5]
*
* var sub1 = subset(myArray, 0, 3);
* var sub2 = subset(myArray, 2, 2);
* print(sub1); // [1,2,3]
* print(sub2); // [3,4]
* }
*
*/
p5.prototype.subset = function(list, start, count) {
if (typeof count !== 'undefined') {
return list.slice(start, start + count);
} else {
return list.slice(start, list.length);
}
};
module.exports = p5;
},{"../core/core":16}],52:[function(require,module,exports){
/**
* @module Data
* @submodule Conversion
* @for p5
* @requires core
*/
'use strict';
var p5 = require('../core/core');
/**
* Converts a string to its floating point representation. The contents of a
* string must resemble a number, or NaN (not a number) will be returned.
* For example, float("1234.56") evaluates to 1234.56, but float("giraffe")
* will return NaN.
*
* @method float
* @param {String} str float string to parse
* @return {Number} floating point representation of string
* @example
*
* var str = '20';
* var diameter = float(str);
* ellipse(width/2, height/2, diameter, diameter);
*
*/
p5.prototype.float = function(str) {
return parseFloat(str);
};
/**
* Converts a boolean, string, or float to its integer representation.
* When an array of values is passed in, then an int array of the same length
* is returned.
*
* @method int
* @param {String|Boolean|Number|Array} n value to parse
* @return {Number} integer representation of value
* @example
*
* print(int("10")); // 10
* print(int(10.31)); // 10
* print(int(-10)); // -10
* print(int(true)); // 1
* print(int(false)); // 0
* print(int([false, true, "10.3", 9.8])); // [0, 1, 10, 9]
*
*/
p5.prototype.int = function(n, radix) {
if (typeof n === 'string') {
radix = radix || 10;
return parseInt(n, radix);
} else if (typeof n === 'number') {
return n | 0;
} else if (typeof n === 'boolean') {
return n ? 1 : 0;
} else if (n instanceof Array) {
return n.map(function(n) { return p5.prototype.int(n, radix); });
}
};
/**
* Converts a boolean, string or number to its string representation.
* When an array of values is passed in, then an array of strings of the same
* length is returned.
*
* @method str
* @param {String|Boolean|Number|Array} n value to parse
* @return {String} string representation of value
* @example
*
* print(str("10")); // "10"
* print(str(10.31)); // "10.31"
* print(str(-10)); // "-10"
* print(str(true)); // "true"
* print(str(false)); // "false"
* print(str([true, "10.3", 9.8])); // [ "true", "10.3", "9.8" ]
*
*/
p5.prototype.str = function(n) {
if (n instanceof Array) {
return n.map(p5.prototype.str);
} else {
return String(n);
}
};
/**
* Converts a number or string to its boolean representation.
* For a number, any non-zero value (positive or negative) evaluates to true,
* while zero evaluates to false. For a string, the value "true" evaluates to
* true, while any other value evaluates to false. When an array of number or
* string values is passed in, then a array of booleans of the same length is
* returned.
*
* @method boolean
* @param {String|Boolean|Number|Array} n value to parse
* @return {Boolean} boolean representation of value
* @example
*
* print(boolean(0)); // false
* print(boolean(1)); // true
* print(boolean("true")); // true
* print(boolean("abcd")); // false
* print(boolean([0, 12, "true"])); // [false, true, false]
*
*/
p5.prototype.boolean = function(n) {
if (typeof n === 'number') {
return n !== 0;
} else if (typeof n === 'string') {
return n.toLowerCase() === 'true';
} else if (typeof n === 'boolean') {
return n;
} else if (n instanceof Array) {
return n.map(p5.prototype.boolean);
}
};
/**
* Converts a number, string or boolean to its byte representation.
* A byte can be only a whole number between -128 and 127, so when a value
* outside of this range is converted, it wraps around to the corresponding
* byte representation. When an array of number, string or boolean values is
* passed in, then an array of bytes the same length is returned.
*
* @method byte
* @param {String|Boolean|Number|Array} n value to parse
* @return {Number} byte representation of value
* @example
*
* print(byte(127)); // 127
* print(byte(128)); // -128
* print(byte(23.4)); // 23
* print(byte("23.4")); // 23
* print(byte(true)); // 1
* print(byte([0, 255, "100"])); // [0, -1, 100]
*
*/
p5.prototype.byte = function(n) {
var nn = p5.prototype.int(n, 10);
if (typeof nn === 'number') {
return ((nn + 128) % 256) - 128;
} else if (nn instanceof Array) {
return nn.map(p5.prototype.byte);
}
};
/**
* Converts a number or string to its corresponding single-character
* string representation. If a string parameter is provided, it is first
* parsed as an integer and then translated into a single-character string.
* When an array of number or string values is passed in, then an array of
* single-character strings of the same length is returned.
*
* @method char
* @param {String|Number|Array} n value to parse
* @return {String} string representation of value
* @example
*
* print(char(65)); // "A"
* print(char("65")); // "A"
* print(char([65, 66, 67])); // [ "A", "B", "C" ]
* print(join(char([65, 66, 67]), '')); // "ABC"
*
*/
p5.prototype.char = function(n) {
if (typeof n === 'number' && !isNaN(n)) {
return String.fromCharCode(n);
} else if (n instanceof Array) {
return n.map(p5.prototype.char);
} else if (typeof n === 'string') {
return p5.prototype.char(parseInt(n, 10));
}
};
/**
* Converts a single-character string to its corresponding integer
* representation. When an array of single-character string values is passed
* in, then an array of integers of the same length is returned.
*
* @method unchar
* @param {String|Array} n value to parse
* @return {Number} integer representation of value
* @example
*
* print(unchar("A")); // 65
* print(unchar(["A", "B", "C"])); // [ 65, 66, 67 ]
* print(unchar(split("ABC", ""))); // [ 65, 66, 67 ]
*
*/
p5.prototype.unchar = function(n) {
if (typeof n === 'string' && n.length === 1) {
return n.charCodeAt(0);
} else if (n instanceof Array) {
return n.map(p5.prototype.unchar);
}
};
/**
* Converts a number to a string in its equivalent hexadecimal notation. If a
* second parameter is passed, it is used to set the number of characters to
* generate in the hexadecimal notation. When an array is passed in, an
* array of strings in hexadecimal notation of the same length is returned.
*
* @method hex
* @param {Number|Array} n value to parse
* @return {String} hexadecimal string representation of value
* @example
*
* print(hex(255)); // "000000FF"
* print(hex(255, 6)); // "0000FF"
* print(hex([0, 127, 255], 6)); // [ "000000", "00007F", "0000FF" ]
*
*/
p5.prototype.hex = function(n, digits) {
digits = (digits === undefined || digits === null) ? digits = 8 : digits;
if (n instanceof Array) {
return n.map(function(n) { return p5.prototype.hex(n, digits); });
} else if (typeof n === 'number') {
if (n < 0) {
n = 0xFFFFFFFF + n + 1;
}
var hex = Number(n).toString(16).toUpperCase();
while (hex.length < digits) {
hex = '0' + hex;
}
if (hex.length >= digits) {
hex = hex.substring(hex.length - digits, hex.length);
}
return hex;
}
};
/**
* Converts a string representation of a hexadecimal number to its equivalent
* integer value. When an array of strings in hexadecimal notation is passed
* in, an array of integers of the same length is returned.
*
* @method unhex
* @param {String|Array} n value to parse
* @return {Number} integer representation of hexadecimal value
* @example
*
* print(unhex("A")); // 10
* print(unhex("FF")); // 255
* print(unhex(["FF", "AA", "00"])); // [ 255, 170, 0 ]
*
*/
p5.prototype.unhex = function(n) {
if (n instanceof Array) {
return n.map(p5.prototype.unhex);
} else {
return parseInt('0x' + n, 16);
}
};
module.exports = p5;
},{"../core/core":16}],53:[function(require,module,exports){
/**
* @module Data
* @submodule String Functions
* @for p5
* @requires core
*/
'use strict';
var p5 = require('../core/core');
//return p5; //LM is this a mistake?
/**
* Combines an array of Strings into one String, each separated by the
* character(s) used for the separator parameter. To join arrays of ints or
* floats, it's necessary to first convert them to Strings using nf() or
* nfs().
*
* @method join
* @param {Array} list array of Strings to be joined
* @param {String} separator String to be placed between each item
* @return {String} joined String
* @example
*
*
* var array = ["Hello", "world!"]
* var separator = " "
* var message = join(array, separator);
* text(message, 5, 50);
*
*
*/
p5.prototype.join = function(list, separator) {
return list.join(separator);
};
/**
* This function is used to apply a regular expression to a piece of text,
* and return matching groups (elements found inside parentheses) as a
* String array. If there are no matches, a null value will be returned.
* If no groups are specified in the regular expression, but the sequence
* matches, an array of length 1 (with the matched text as the first element
* of the array) will be returned.
*
* To use the function, first check to see if the result is null. If the
* result is null, then the sequence did not match at all. If the sequence
* did match, an array is returned.
*
* If there are groups (specified by sets of parentheses) in the regular
* expression, then the contents of each will be returned in the array.
* Element [0] of a regular expression match returns the entire matching
* string, and the match groups start at element [1] (the first group is [1],
* the second [2], and so on).
*
* @method match
* @param {String} str the String to be searched
* @param {String} regexp the regexp to be used for matching
* @return {Array} Array of Strings found
* @example
*
*
* var string = "Hello p5js*!"
* var regexp = "p5js\\*"
* var match = match(string, regexp);
* text(match, 5, 50);
*
*
*/
p5.prototype.match = function(str, reg) {
return str.match(reg);
};
/**
* This function is used to apply a regular expression to a piece of text,
* and return a list of matching groups (elements found inside parentheses)
* as a two-dimensional String array. If there are no matches, a null value
* will be returned. If no groups are specified in the regular expression,
* but the sequence matches, a two dimensional array is still returned, but
* the second dimension is only of length one.
*
* To use the function, first check to see if the result is null. If the
* result is null, then the sequence did not match at all. If the sequence
* did match, a 2D array is returned.
*
* If there are groups (specified by sets of parentheses) in the regular
* expression, then the contents of each will be returned in the array.
* Assuming a loop with counter variable i, element [i][0] of a regular
* expression match returns the entire matching string, and the match groups
* start at element [i][1] (the first group is [i][1], the second [i][2],
* and so on).
*
* @method matchAll
* @param {String} str the String to be searched
* @param {String} regexp the regexp to be used for matching
* @return {Array} 2d Array of Strings found
* @example
*
*
* var string = "Hello p5js*! Hello world!"
* var regexp = "Hello"
* matchAll(string, regexp);
*
*
*/
p5.prototype.matchAll = function(str, reg) {
var re = new RegExp(reg, 'g');
var match = re.exec(str);
var matches = [];
while (match !== null) {
matches.push(match);
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
match = re.exec(str);
}
return matches;
};
/**
* Utility function for formatting numbers into strings. There are two
* versions: one for formatting floats, and one for formatting ints.
* The values for the digits, left, and right parameters should always
* be positive integers.
*
* @method nf
* @param {Number|Array} num the Number to format
* @param {Number} [left] number of digits to the left of the
* decimal point
* @param {Number} [right] number of digits to the right of the
* decimal point
* @return {String|Array} formatted String
* @example
*
*
* function setup() {
* background(200);
* var num = 112.53106115;
*
* noStroke();
* fill(0);
* textSize(14);
* // Draw formatted numbers
* text(nf(num, 5, 2), 10, 20);
*
* text(nf(num, 4, 3), 10, 55);
*
* text(nf(num, 3, 6), 10, 85);
*
* // Draw dividing lines
* stroke(120);
* line(0, 30, width, 30);
* line(0, 65, width, 65);
* }
*
*
*/
p5.prototype.nf = function () {
if (arguments[0] instanceof Array) {
var a = arguments[1];
var b = arguments[2];
return arguments[0].map(function (x) {
return doNf(x, a, b);
});
}
else{
var typeOfFirst = Object.prototype.toString.call(arguments[0]);
if(typeOfFirst === '[object Arguments]'){
if(arguments[0].length===3){
return this.nf(arguments[0][0],arguments[0][1],arguments[0][2]);
}
else if(arguments[0].length===2){
return this.nf(arguments[0][0],arguments[0][1]);
}
else{
return this.nf(arguments[0][0]);
}
}
else {
return doNf.apply(this, arguments);
}
}
};
function doNf() {
var num = arguments[0];
var neg = num < 0;
var n = neg ? num.toString().substring(1) : num.toString();
var decimalInd = n.indexOf('.');
var intPart = decimalInd !== -1 ? n.substring(0, decimalInd) : n;
var decPart = decimalInd !== -1 ? n.substring(decimalInd + 1) : '';
var str = neg ? '-' : '';
if (arguments.length === 3) {
var decimal = '';
if(decimalInd !== -1 || arguments[2] - decPart.length > 0){
decimal = '.';
}
if (decPart.length > arguments[2]) {
decPart = decPart.substring(0, arguments[2]);
}
for (var i = 0; i < arguments[1] - intPart.length; i++) {
str += '0';
}
str += intPart;
str += decimal;
str += decPart;
for (var j = 0; j < arguments[2] - decPart.length; j++) {
str += '0';
}
return str;
}
else {
for (var k = 0; k < Math.max(arguments[1] - intPart.length, 0); k++) {
str += '0';
}
str += n;
return str;
}
}
/**
* Utility function for formatting numbers into strings and placing
* appropriate commas to mark units of 1000. There are two versions: one
* for formatting ints, and one for formatting an array of ints. The value
* for the right parameter should always be a positive integer.
*
* @method nfc
* @param {Number|Array} num the Number to format
* @param {Number} [right] number of digits to the right of the
* decimal point
* @return {String|Array} formatted String
* @example
*
*
* function setup() {
* background(200);
* var num = 11253106.115;
* var numArr = new Array(1,1,2);
*
* noStroke();
* fill(0);
* textSize(12);
*
* // Draw formatted numbers
* text(nfc(num, 4, 2), 10, 30);
* text(nfc(numArr, 2, 1), 10, 80);
*
* // Draw dividing line
* stroke(120);
* line(0, 50, width, 50);
* }
*
*
*/
p5.prototype.nfc = function () {
if (arguments[0] instanceof Array) {
var a = arguments[1];
return arguments[0].map(function (x) {
return doNfc(x, a);
});
} else {
return doNfc.apply(this, arguments);
}
};
function doNfc() {
var num = arguments[0].toString();
var dec = num.indexOf('.');
var rem = dec !== -1 ? num.substring(dec) : '';
var n = dec !== -1 ? num.substring(0, dec) : num;
n = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
if (arguments[1] === 0) {
rem = '';
}
else if(arguments[1] !== undefined){
if(arguments[1] > rem.length){
rem+= dec === -1 ? '.' : '';
var len = arguments[1] - rem.length + 1;
for(var i =0; i< len; i++){
rem += '0';
}
}
else{
rem = rem.substring(0, arguments[1] + 1);
}
}
return n + rem;
}
/**
* Utility function for formatting numbers into strings. Similar to nf() but
* puts a "+" in front of positive numbers and a "-" in front of negative
* numbers. There are two versions: one for formatting floats, and one for
* formatting ints. The values for left, and right parameters
* should always be positive integers.
*
* @method nfp
* @param {Number|Array} num the Number to format
* @param {Number} [left] number of digits to the left of the decimal
* point
* @param {Number} [right] number of digits to the right of the
* decimal point
* @return {String|Array} formatted String
* @example
*
*
* function setup() {
* background(200);
* var num1 = 11253106.115;
* var num2 = -11253106.115;
*
* noStroke();
* fill(0);
* textSize(12);
*
* // Draw formatted numbers
* text(nfp(num1, 4, 2), 10, 30);
* text(nfp(num2, 4, 2), 10, 80);
*
* // Draw dividing line
* stroke(120);
* line(0, 50, width, 50);
* }
*
*
*/
p5.prototype.nfp = function() {
var nfRes = this.nf.apply(this, arguments);
if (nfRes instanceof Array) {
return nfRes.map(addNfp);
} else {
return addNfp(nfRes);
}
};
function addNfp() {
return (
parseFloat(arguments[0]) > 0) ?
'+'+arguments[0].toString() :
arguments[0].toString();
}
/**
* Utility function for formatting numbers into strings. Similar to nf() but
* puts a " " (space) in front of positive numbers and a "-" in front of
* negative numbers. There are two versions: one for formatting floats, and
* one for formatting ints. The values for the digits, left, and right
* parameters should always be positive integers.
*
* @method nfs
* @param {Number|Array} num the Number to format
* @param {Number} [left] number of digits to the left of the decimal
* point
* @param {Number} [right] number of digits to the right of the
* decimal point
* @return {String|Array} formatted String
* @example
*
*
* function setup() {
* background(200);
* var num1 = 11253106.115;
* var num2 = -11253106.115;
*
* noStroke();
* fill(0);
* textSize(12);
* // Draw formatted numbers
* text(nfs(num1, 4, 2), 10, 30);
*
* text(nfs(num2, 4, 2), 10, 80);
*
* // Draw dividing line
* stroke(120);
* line(0, 50, width, 50);
* }
*
*
*/
p5.prototype.nfs = function() {
var nfRes = this.nf.apply(this, arguments);
if (nfRes instanceof Array) {
return nfRes.map(addNfs);
} else {
return addNfs(nfRes);
}
};
function addNfs() {
return (
parseFloat(arguments[0]) > 0) ?
' '+arguments[0].toString() :
arguments[0].toString();
}
/**
* The split() function maps to String.split(), it breaks a String into
* pieces using a character or string as the delimiter. The delim parameter
* specifies the character or characters that mark the boundaries between
* each piece. A String[] array is returned that contains each of the pieces.
*
* The splitTokens() function works in a similar fashion, except that it
* splits using a range of characters instead of a specific character or
* sequence.
*
* @method split
* @param {String} value the String to be split
* @param {String} delim the String used to separate the data
* @return {Array} Array of Strings
* @example
*
*
*var names = "Pat,Xio,Alex"
* var splitString = split(names, ",");
* text(splitString[0], 5, 30);
* text(splitString[1], 5, 50);
* text(splitString[2], 5, 70);
*
*
*/
p5.prototype.split = function(str, delim) {
return str.split(delim);
};
/**
* The splitTokens() function splits a String at one or many character
* delimiters or "tokens." The delim parameter specifies the character or
* characters to be used as a boundary.
*
* If no delim characters are specified, any whitespace character is used to
* split. Whitespace characters include tab (\t), line feed (\n), carriage
* return (\r), form feed (\f), and space.
*
* @method splitTokens
* @param {String} value the String to be split
* @param {String} [delim] list of individual Strings that will be used as
* separators
* @return {Array} Array of Strings
* @example
*
*
* function setup() {
* var myStr = "Mango, Banana, Lime";
* var myStrArr = splitTokens(myStr, ",");
*
* print(myStrArr); // prints : ["Mango"," Banana"," Lime"]
* }
*
*
*/
p5.prototype.splitTokens = function() {
var d = (arguments.length > 0) ? arguments[1] : /\s/g;
return arguments[0].split(d).filter(function(n){return n;});
};
/**
* Removes whitespace characters from the beginning and end of a String. In
* addition to standard whitespace characters such as space, carriage return,
* and tab, this function also removes the Unicode "nbsp" character.
*
* @method trim
* @param {String|Array} [str] a String or Array of Strings to be trimmed
* @return {String|Array} a trimmed String or Array of Strings
* @example
*
*
* var string = trim(" No new lines\n ");
* text(string +" here", 2, 50);
*
*
*/
p5.prototype.trim = function(str) {
if (str instanceof Array) {
return str.map(this.trim);
} else {
return str.trim();
}
};
module.exports = p5;
},{"../core/core":16}],54:[function(require,module,exports){
/**
* @module Input
* @submodule Time & Date
* @for p5
* @requires core
*/
'use strict';
var p5 = require('../core/core');
/**
* p5.js communicates with the clock on your computer. The day() function
* returns the current day as a value from 1 - 31.
*
* @method day
* @return {Number} the current day
* @example
*
*
* var day = day();
* text("Current day: \n"+day, 5, 50);
*
*
*/
p5.prototype.day = function() {
return new Date().getDate();
};
/**
* p5.js communicates with the clock on your computer. The hour() function
* returns the current hour as a value from 0 - 23.
*
* @method hour
* @return {Number} the current hour
* @example
*
*
* var hour = hour();
* text("Current hour:\n"+hour, 5, 50);
*
*
*/
p5.prototype.hour = function() {
return new Date().getHours();
};
/**
* p5.js communicates with the clock on your computer. The minute() function
* returns the current minute as a value from 0 - 59.
*
* @method minute
* @return {Number} the current minute
* @example
*
*
* var minute = minute();
* text("Current minute: \n:"+minute, 5, 50);
*
*
*/
p5.prototype.minute = function() {
return new Date().getMinutes();
};
/**
* Returns the number of milliseconds (thousandths of a second) since
* starting the program. This information is often used for timing events and
* animation sequences.
*
* @method millis
* @return {Number} the number of milliseconds since starting the program
* @example
*
*
* var millisecond = millis();
* text("Milliseconds \nrunning: "+millisecond, 5, 50);
*
*
*/
p5.prototype.millis = function() {
return window.performance.now();
};
/**
* p5.js communicates with the clock on your computer. The month() function
* returns the current month as a value from 1 - 12.
*
* @method month
* @return {Number} the current month
* @example
*
*
* var month = month();
* text("Current month: \n"+month, 5, 50);
*
*
*/
p5.prototype.month = function() {
return new Date().getMonth() + 1; //January is 0!
};
/**
* p5.js communicates with the clock on your computer. The second() function
* returns the current second as a value from 0 - 59.
*
* @method second
* @return {Number} the current second
* @example
*
*
* var second = second();
* text("Current second: \n" +second, 5, 50);
*
*
*/
p5.prototype.second = function() {
return new Date().getSeconds();
};
/**
* p5.js communicates with the clock on your computer. The year() function
* returns the current year as an integer (2014, 2015, 2016, etc).
*
* @method year
* @return {Number} the current year
* @example
*
*
* var year = year();
* text("Current year: \n" +year, 5, 50);
*
*
*/
p5.prototype.year = function() {
return new Date().getFullYear();
};
module.exports = p5;
},{"../core/core":16}]},{},[7])(7)
});
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.opentype = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0,"No "+e+" specified.")}var n=[],i=this;e("familyName"),e("weightName"),e("manufacturer"),e("copyright"),e("version"),t(this.unitsPerEm>0,"No unitsPerEm specified.")},Font.prototype.toTables=function(){return sfnt.fontToTable(this)},Font.prototype.toBuffer=function(){for(var t=this.toTables(),e=t.encode(),n=new ArrayBuffer(e.length),i=new Uint8Array(n),o=0;oh;h+=1){var d=parse.getTag(i,f),m=parse.getULong(i,f+8);switch(d){case"cmap":l.tables.cmap=cmap.parse(i,m),l.encoding=new encoding.CmapEncoding(l.tables.cmap),l.encoding||(l.supported=!1);break;case"head":l.tables.head=head.parse(i,m),l.unitsPerEm=l.tables.head.unitsPerEm,a=l.tables.head.indexToLocFormat;break;case"hhea":l.tables.hhea=hhea.parse(i,m),l.ascender=l.tables.hhea.ascender,l.descender=l.tables.hhea.descender,l.numberOfHMetrics=l.tables.hhea.numberOfHMetrics;break;case"hmtx":r=m;break;case"maxp":l.tables.maxp=maxp.parse(i,m),l.numGlyphs=l.tables.maxp.numGlyphs;break;case"name":l.tables.name=_name.parse(i,m),l.familyName=l.tables.name.fontFamily,l.styleName=l.tables.name.fontSubfamily;break;case"OS/2":l.tables.os2=os2.parse(i,m);break;case"post":l.tables.post=post.parse(i,m),l.glyphNames=new encoding.GlyphNames(l.tables.post);break;case"glyf":s=m;break;case"loca":t=m;break;case"CFF ":n=m;break;case"kern":o=m;break;case"GPOS":p=m}f+=16}if(s&&t){var b=0===a,g=loca.parse(i,t,l.numGlyphs,b);l.glyphs=glyf.parse(i,s,g,l),hmtx.parse(i,r,l.numberOfHMetrics,l.numGlyphs,l.glyphs),encoding.addGlyphNames(l)}else n?(cff.parse(i,n,l),encoding.addGlyphNames(l)):l.supported=!1;return l.supported&&(l.kerningPairs=o?kern.parse(i,o):{},p&&gpos.parse(i,p,l)),l}function load(e,a){var r="undefined"==typeof window,s=r?loadFromFile:loadFromUrl;s(e,function(e,r){if(e)return a(e);var s=parseBuffer(r);return s.supported?a(null,s):a("Font is not supported (is this a Postscript font?)")})}var encoding=require("./encoding"),_font=require("./font"),glyph=require("./glyph"),parse=require("./parse"),path=require("./path"),cmap=require("./tables/cmap"),cff=require("./tables/cff"),glyf=require("./tables/glyf"),gpos=require("./tables/gpos"),head=require("./tables/head"),hhea=require("./tables/hhea"),hmtx=require("./tables/hmtx"),kern=require("./tables/kern"),loca=require("./tables/loca"),maxp=require("./tables/maxp"),_name=require("./tables/name"),os2=require("./tables/os2"),post=require("./tables/post");exports._parse=parse,exports.Font=_font.Font,exports.Glyph=glyph.Glyph,exports.Path=path.Path,exports.parse=parseBuffer,exports.load=load;
},{"./encoding":3,"./font":4,"./glyph":5,"./parse":7,"./path":8,"./tables/cff":10,"./tables/cmap":11,"./tables/glyf":12,"./tables/gpos":13,"./tables/head":14,"./tables/hhea":15,"./tables/hmtx":16,"./tables/kern":17,"./tables/loca":18,"./tables/maxp":19,"./tables/name":20,"./tables/os2":21,"./tables/post":22,"fs":undefined}],7:[function(require,module,exports){
"use strict";function Parser(t,e){this.data=t,this.offset=e,this.relativeOffset=0}exports.getByte=function(t,e){return t.getUint8(e)},exports.getCard8=exports.getByte,exports.getUShort=function(t,e){return t.getUint16(e,!1)},exports.getCard16=exports.getUShort,exports.getShort=function(t,e){return t.getInt16(e,!1)},exports.getULong=function(t,e){return t.getUint32(e,!1)},exports.getFixed=function(t,e){var r=t.getInt16(e,!1),s=t.getUint16(e+2,!1);return r+s/65535},exports.getTag=function(t,e){for(var r="",s=e;e+4>s;s+=1)r+=String.fromCharCode(t.getInt8(s));return r},exports.getOffset=function(t,e,r){for(var s=0,o=0;r>o;o+=1)s<<=8,s+=t.getUint8(e+o);return s},exports.getBytes=function(t,e,r){for(var s=[],o=e;r>o;o+=1)s.push(t.getUint8(o));return s},exports.bytesToString=function(t){for(var e="",r=0;ro;o++)e[o]=exports.getUShort(r,s),s+=2;return this.relativeOffset+=2*t,e},Parser.prototype.parseString=function(t){var e=this.data,r=this.offset+this.relativeOffset,s="";this.relativeOffset+=t;for(var o=0;t>o;o++)s+=String.fromCharCode(e.getUint8(r+o));return s},Parser.prototype.parseTag=function(){return this.parseString(4)},Parser.prototype.parseLongDateTime=function(){var t=exports.getULong(this.data,this.offset+this.relativeOffset+4);return this.relativeOffset+=8,t},Parser.prototype.parseFixed=function(){var t=exports.getULong(this.data,this.offset+this.relativeOffset);return this.relativeOffset+=4,t/65536},Parser.prototype.parseVersion=function(){var t=exports.getUShort(this.data,this.offset+this.relativeOffset),e=exports.getUShort(this.data,this.offset+this.relativeOffset+2);return this.relativeOffset+=4,t+e/4096/10},Parser.prototype.skip=function(t,e){void 0===e&&(e=1),this.relativeOffset+=typeOffsets[t]*e},exports.Parser=Parser;
},{}],8:[function(require,module,exports){
"use strict";function Path(){this.commands=[],this.fill="black",this.stroke=null,this.strokeWidth=1}Path.prototype.moveTo=function(t,o){this.commands.push({type:"M",x:t,y:o})},Path.prototype.lineTo=function(t,o){this.commands.push({type:"L",x:t,y:o})},Path.prototype.curveTo=Path.prototype.bezierCurveTo=function(t,o,e,i,s,h){this.commands.push({type:"C",x1:t,y1:o,x2:e,y2:i,x:s,y:h})},Path.prototype.quadTo=Path.prototype.quadraticCurveTo=function(t,o,e,i){this.commands.push({type:"Q",x1:t,y1:o,x:e,y:i})},Path.prototype.close=Path.prototype.closePath=function(){this.commands.push({type:"Z"})},Path.prototype.extend=function(t){t.commands&&(t=t.commands),Array.prototype.push.apply(this.commands,t)},Path.prototype.draw=function(t){t.beginPath();for(var o=0;o=0&&e>0&&(t+=" "),t+=o(i)}return t}t=void 0!==t?t:2;for(var i="",s=0;s"},exports.Path=Path;
},{}],9:[function(require,module,exports){
"use strict";function Table(e,t,i){var s;for(s=0;sr;r+=1)i.push(parse.getOffset(e,p,f)),p+=f;s=n+i[o]}else s=t+2;for(r=0;r>4,i=15&n;if(s===a)break;if(t+=r[s],i===a)break;t+=r[i]}return parseFloat(t)}function parseOperand(e,t){var a,r,n,s;if(28===t)return a=e.parseByte(),r=e.parseByte(),a<<8|r;if(29===t)return a=e.parseByte(),r=e.parseByte(),n=e.parseByte(),s=e.parseByte(),a<<24|r<<16|n<<8|s;if(30===t)return parseFloatOperand(e);if(t>=32&&246>=t)return t-139;if(t>=247&&250>=t)return a=e.parseByte(),256*(t-247)+a+108;if(t>=251&&254>=t)return a=e.parseByte(),256*-(t-251)-a-108;throw new Error("Invalid b0 "+t)}function entriesToObject(e){for(var t={},a=0;a=i?(12===i&&(i=1200+r.parseByte()),n.push([i,s]),s=[]):s.push(parseOperand(r,i))}return entriesToObject(n)}function getCFFString(e,t){return t=390>=t?encoding.cffStandardStrings[t]:e[t-391]}function interpretDict(e,t,a){for(var r={},n=0;nn;n+=1)s=h.parseSID(),o.push(getCFFString(r,s));else if(1===f)for(;o.length<=a;)for(s=h.parseSID(),i=h.parseCard8(),n=0;i>=n;n+=1)o.push(getCFFString(r,s)),s+=1;else{if(2!==f)throw new Error("Unknown charset format "+f);for(;o.length<=a;)for(s=h.parseSID(),i=h.parseCard16(),n=0;i>=n;n+=1)o.push(getCFFString(r,s)),s+=1}return o}function parseCFFEncoding(e,t,a){var r,n,s={},i=new parse.Parser(e,t),h=i.parseCard8();if(0===h){var o=i.parseCard8();for(r=0;o>r;r+=1)n=i.parseCard8(),s[n]=r}else{if(1!==h)throw new Error("Unknown encoding format "+h);var f=i.parseCard8();for(n=1,r=0;f>r;r+=1)for(var p=i.parseCard8(),u=i.parseCard8(),l=p;p+u>=l;l+=1)s[l]=n,n+=1}return new encoding.CffEncoding(s,a)}function parseCFFCharstring(e,t,a){function r(e,t){v&&p.closePath(),p.moveTo(e,t),v=!0}function n(){var e;e=u.length%2!==0,e&&!c&&(d=u.shift()+t.nominalWidthX),l+=u.length>>1,u.length=0,c=!0}function s(e){for(var y,b,T,C,I,F,D,x,k,S,E,B,w=0;w1&&!c&&(d=u.shift()+t.nominalWidthX,c=!0),m+=u.pop(),r(g,m);break;case 5:for(;u.length>0;)g+=u.shift(),m+=u.shift(),p.lineTo(g,m);break;case 6:for(;u.length>0&&(g+=u.shift(),p.lineTo(g,m),0!==u.length);)m+=u.shift(),p.lineTo(g,m);break;case 7:for(;u.length>0&&(m+=u.shift(),p.lineTo(g,m),0!==u.length);)g+=u.shift(),p.lineTo(g,m);break;case 8:for(;u.length>0;)i=g+u.shift(),h=m+u.shift(),o=i+u.shift(),f=h+u.shift(),g=o+u.shift(),m=f+u.shift(),p.curveTo(i,h,o,f,g,m);break;case 10:I=u.pop()+t.subrsBias,F=t.subrs[I],F&&s(F);break;case 11:return;case 12:switch(M=e[w],w+=1,M){case 35:i=g+u.shift(),h=m+u.shift(),o=i+u.shift(),f=h+u.shift(),D=o+u.shift(),x=f+u.shift(),k=D+u.shift(),S=x+u.shift(),E=k+u.shift(),B=S+u.shift(),g=E+u.shift(),m=B+u.shift(),u.shift(),p.curveTo(i,h,o,f,D,x),p.curveTo(k,S,E,B,g,m);break;case 34:i=g+u.shift(),h=m,o=i+u.shift(),f=h+u.shift(),D=o+u.shift(),x=f,k=D+u.shift(),S=f,E=k+u.shift(),B=m,g=E+u.shift(),p.curveTo(i,h,o,f,D,x),p.curveTo(k,S,E,B,g,m);break;case 36:i=g+u.shift(),h=m+u.shift(),o=i+u.shift(),f=h+u.shift(),D=o+u.shift(),x=f,k=D+u.shift(),S=f,E=k+u.shift(),B=S+u.shift(),g=E+u.shift(),p.curveTo(i,h,o,f,D,x),p.curveTo(k,S,E,B,g,m);break;case 37:i=g+u.shift(),h=m+u.shift(),o=i+u.shift(),f=h+u.shift(),D=o+u.shift(),x=f+u.shift(),k=D+u.shift(),S=x+u.shift(),E=k+u.shift(),B=S+u.shift(),Math.abs(E-g)>Math.abs(B-m)?g=E+u.shift():m=B+u.shift(),p.curveTo(i,h,o,f,D,x),p.curveTo(k,S,E,B,g,m);break;default:console.log("Glyph "+a+": unknown operator 1200"+M),u.length=0}break;case 14:u.length>0&&!c&&(d=u.shift()+t.nominalWidthX,c=!0),v&&(p.closePath(),v=!1);break;case 18:n();break;case 19:case 20:n(),w+=l+7>>3;break;case 21:u.length>2&&!c&&(d=u.shift()+t.nominalWidthX,c=!0),m+=u.pop(),g+=u.pop(),r(g,m);break;case 22:u.length>1&&!c&&(d=u.shift()+t.nominalWidthX,c=!0),g+=u.pop(),r(g,m);break;case 23:n();break;case 24:for(;u.length>2;)i=g+u.shift(),h=m+u.shift(),o=i+u.shift(),f=h+u.shift(),g=o+u.shift(),m=f+u.shift(),p.curveTo(i,h,o,f,g,m);g+=u.shift(),m+=u.shift(),p.lineTo(g,m);break;case 25:for(;u.length>6;)g+=u.shift(),m+=u.shift(),p.lineTo(g,m);i=g+u.shift(),h=m+u.shift(),o=i+u.shift(),f=h+u.shift(),g=o+u.shift(),m=f+u.shift(),p.curveTo(i,h,o,f,g,m);break;case 26:for(u.length%2&&(g+=u.shift());u.length>0;)i=g,h=m+u.shift(),o=i+u.shift(),f=h+u.shift(),g=o,m=f+u.shift(),p.curveTo(i,h,o,f,g,m);break;case 27:for(u.length%2&&(m+=u.shift());u.length>0;)i=g+u.shift(),h=m,o=i+u.shift(),f=h+u.shift(),g=o+u.shift(),m=f,p.curveTo(i,h,o,f,g,m);break;case 28:y=e[w],b=e[w+1],u.push((y<<24|b<<16)>>16),w+=2;break;case 29:I=u.pop()+t.gsubrsBias,F=t.gsubrs[I],F&&s(F);break;case 30:for(;u.length>0&&(i=g,h=m+u.shift(),o=i+u.shift(),f=h+u.shift(),g=o+u.shift(),m=f+(1===u.length?u.shift():0),p.curveTo(i,h,o,f,g,m),0!==u.length);)i=g+u.shift(),h=m,o=i+u.shift(),f=h+u.shift(),m=f+u.shift(),g=o+(1===u.length?u.shift():0),p.curveTo(i,h,o,f,g,m);break;case 31:for(;u.length>0&&(i=g+u.shift(),h=m,o=i+u.shift(),f=h+u.shift(),m=f+u.shift(),g=o+(1===u.length?u.shift():0),p.curveTo(i,h,o,f,g,m),0!==u.length);)i=g,h=m+u.shift(),o=i+u.shift(),f=h+u.shift(),g=o+u.shift(),m=f+(1===u.length?u.shift():0),p.curveTo(i,h,o,f,g,m);break;default:32>M?console.log("Glyph "+a+": unknown operator "+M):247>M?u.push(M-139):251>M?(y=e[w],w+=1,u.push(256*(M-247)+y+108)):255>M?(y=e[w],w+=1,u.push(256*-(M-251)-y-108)):(y=e[w],b=e[w+1],T=e[w+2],C=e[w+3],w+=4,u.push((y<<24|b<<16|T<<8|C)/65536))}}}var i,h,o,f,p=new path.Path,u=[],l=0,c=!1,d=t.defaultWidthX,v=!1,g=0,m=0;s(e);var y=new _glyph.Glyph({font:t,index:a});return y.path=p,y.advanceWidth=d,y}function calcCFFSubroutineBias(e){var t;return t=e.length<1240?107:e.length<33900?1131:32768}function parseCFFTable(e,t,a){a.tables.cff={};var r=parseCFFHeader(e,t),n=parseCFFIndex(e,r.endOffset,parse.bytesToString),s=parseCFFIndex(e,n.endOffset),i=parseCFFIndex(e,s.endOffset,parse.bytesToString),h=parseCFFIndex(e,i.endOffset);a.gsubrs=h.objects,a.gsubrsBias=calcCFFSubroutineBias(a.gsubrs);var o=new DataView(new Uint8Array(s.objects[0]).buffer),f=parseCFFTopDict(o,i.objects);a.tables.cff.topDict=f;var p=t+f["private"][1],u=parseCFFPrivateDict(e,p,f["private"][0],i.objects);if(a.defaultWidthX=u.defaultWidthX,a.nominalWidthX=u.nominalWidthX,0!==u.subrs){var l=p+u.subrs,c=parseCFFIndex(e,l);a.subrs=c.objects,a.subrsBias=calcCFFSubroutineBias(a.subrs)}else a.subrs=[],a.subrsBias=0;var d=parseCFFIndex(e,t+f.charStrings);a.nGlyphs=d.objects.length;var v=parseCFFCharset(e,t+f.charset,a.nGlyphs,i.objects);a.cffEncoding=0===f.encoding?new encoding.CffEncoding(encoding.cffStandardEncoding,v):1===f.encoding?new encoding.CffEncoding(encoding.cffExpertEncoding,v):parseCFFEncoding(e,t+f.encoding,v),a.encoding=a.encoding||a.cffEncoding,a.glyphs=[];for(var g=0;g=0&&(a=r),r=t.indexOf(e),r>=0?a=r+encoding.cffStandardStrings.length:(a=encoding.cffStandardStrings.length+t.length,t.push(e)),a}function makeHeader(){return new table.Table("Header",[{name:"major",type:"Card8",value:1},{name:"minor",type:"Card8",value:0},{name:"hdrSize",type:"Card8",value:4},{name:"major",type:"Card8",value:1}])}function makeNameIndex(e){var t=new table.Table("Name INDEX",[{name:"names",type:"INDEX",value:[]}]);t.names=[];for(var a=0;a>1,o.skip("uShort",3),r.glyphIndexMap={};var g=new parse.Parser(e,a+n+14),m=new parse.Parser(e,a+n+16+2*p),u=new parse.Parser(e,a+n+16+4*p),h=new parse.Parser(e,a+n+16+6*p),c=a+n+16+8*p;for(t=0;p-1>t;t+=1)for(var f,d=g.parseUShort(),S=m.parseUShort(),i=u.parseShort(),v=h.parseUShort(),U=S;d>=U;U+=1)0!==v?(c=h.offset+h.relativeOffset-2,c+=v,c+=2*(U-S),f=parse.getUShort(e,c),0!==f&&(f=f+i&65535)):f=U+i&65535,r.glyphIndexMap[U]=f;return r}function addSegment(e,a,t){e.segments.push({end:a,start:a,delta:-(a-t),offset:0})}function addTerminatorSegment(e){e.segments.push({end:65535,start:65535,delta:1,offset:0})}function makeCmapTable(e){var a,t=new table.Table("cmap",[{name:"version",type:"USHORT",value:0},{name:"numTables",type:"USHORT",value:1},{name:"platformID",type:"USHORT",value:3},{name:"encodingID",type:"USHORT",value:1},{name:"offset",type:"ULONG",value:12},{name:"format",type:"USHORT",value:4},{name:"length",type:"USHORT",value:0},{name:"language",type:"USHORT",value:0},{name:"segCountX2",type:"USHORT",value:0},{name:"searchRange",type:"USHORT",value:0},{name:"entrySelector",type:"USHORT",value:0},{name:"rangeShift",type:"USHORT",value:0}]);for(t.segments=[],a=0;aa;a+=1){var u=t.segments[a];l=l.concat({name:"end_"+a,type:"USHORT",value:u.end}),o=o.concat({name:"start_"+a,type:"USHORT",value:u.start}),p=p.concat({name:"idDelta_"+a,type:"SHORT",value:u.delta}),g=g.concat({name:"idRangeOffset_"+a,type:"USHORT",value:u.offset}),void 0!==u.glyphId&&(m=m.concat({name:"glyph_"+a,type:"USHORT",value:u.glyphId}))}return t.fields=t.fields.concat(l),t.fields.push({name:"reservedPad",type:"USHORT",value:0}),t.fields=t.fields.concat(o),t.fields=t.fields.concat(p),t.fields=t.fields.concat(g),t.fields=t.fields.concat(m),t.length=14+2*l.length+2+2*o.length+2*p.length+2*g.length+2*m.length,t}var check=require("../check"),parse=require("../parse"),table=require("../table");exports.parse=parseCmapTable,exports.make=makeCmapTable;
},{"../check":1,"../parse":7,"../table":9}],12:[function(require,module,exports){
"use strict";function parseGlyphCoordinate(r,e,t,o,n){var a;return(e&o)>0?(a=r.parseByte(),0===(e&n)&&(a=-a),a=t+a):a=(e&n)>0?t:t+r.parseShort(),a}function parseGlyph(r,e,t,o){var n=new parse.Parser(r,e),a=new _glyph.Glyph({font:o,index:t});a.numberOfContours=n.parseShort(),a.xMin=n.parseShort(),a.yMin=n.parseShort(),a.xMax=n.parseShort(),a.yMax=n.parseShort();var s,p;if(a.numberOfContours>0){var u,i=a.endPointIndices=[];for(u=0;uu;u+=1)if(p=n.parseByte(),s.push(p),(8&p)>0)for(var h=n.parseByte(),f=0;h>f;f+=1)s.push(p),u+=1;if(check.argument(s.length===l,"Bad flags."),i.length>0){var y,c=[];if(l>0){for(u=0;l>u;u+=1)p=s[u],y={},y.onCurve=!!(1&p),y.lastPointOfContour=i.indexOf(u)>=0,c.push(y);var v=0;for(u=0;l>u;u+=1)p=s[u],y=c[u],y.x=parseGlyphCoordinate(n,p,v,2,16),v=y.x;var x=0;for(u=0;l>u;u+=1)p=s[u],y=c[u],y.y=parseGlyphCoordinate(n,p,x,4,32),x=y.y}a.points=c}else a.points=[]}else if(0===a.numberOfContours)a.points=[];else{a.isComposite=!0,a.points=[],a.components=[];for(var C=!0;C;){s=n.parseUShort();var g={glyphIndex:n.parseUShort(),xScale:1,scale01:0,scale10:0,yScale:1,dx:0,dy:0};(1&s)>0?(g.dx=n.parseShort(),g.dy=n.parseShort()):(g.dx=n.parseChar(),g.dy=n.parseChar()),(8&s)>0?g.xScale=g.yScale=n.parseF2Dot14():(64&s)>0?(g.xScale=n.parseF2Dot14(),g.yScale=n.parseF2Dot14()):(128&s)>0&&(g.xScale=n.parseF2Dot14(),g.scale01=n.parseF2Dot14(),g.scale10=n.parseF2Dot14(),g.yScale=n.parseF2Dot14()),a.components.push(g),C=!!(32&s)}}return a}function transformPoints(r,e){for(var t=[],o=0;oo;o++)t[a.parseTag()]={offset:a.parseUShort()};return t}function parseCoverageTable(r,e){var a=new parse.Parser(r,e),s=a.parseUShort(),t=a.parseUShort();if(1===s)return a.parseUShortList(t);if(2===s){for(var o=[];t--;)for(var p=a.parseUShort(),n=a.parseUShort(),f=a.parseUShort(),i=p;n>=i;i++)o[f++]=i;return o}}function parseClassDefTable(r,e){var a=new parse.Parser(r,e),s=a.parseUShort();if(1===s){var t=a.parseUShort(),o=a.parseUShort(),p=a.parseUShortList(o);return function(r){return p[r-t]||0}}if(2===s){for(var n=a.parseUShort(),f=[],i=[],h=[],S=0;n>S;S++)f[S]=a.parseUShort(),i[S]=a.parseUShort(),h[S]=a.parseUShort();return function(r){for(var e=0,a=f.length-1;a>e;){var s=e+a+1>>1;rU;U++){var l=v[U],g=h[l];if(!g){g={},t.relativeOffset=l;for(var T=t.parseUShort();T--;){var c=t.parseUShort();f&&(a=t.parseShort()),i&&(s=t.parseShort()),g[c]=a}}u[n[U]]=g}return function(r,e){var a=u[r];return a?a[e]:void 0}}if(2===o){for(var b=t.parseUShort(),P=t.parseUShort(),L=t.parseUShort(),k=t.parseUShort(),d=parseClassDefTable(r,e+b),w=parseClassDefTable(r,e+P),O=[],C=0;L>C;C++)for(var G=O[C]=[],K=0;k>K;K++)f&&(a=t.parseShort()),i&&(s=t.parseShort()),G[K]=a;var V={};for(C=0;Ch;h++)i.push(parsePairPosSubTable(r,e+n[h]));f.getKerningValue=function(r,e){for(var a=i.length;a--;){var s=i[a](r,e);if(void 0!==s)return s}return 0}}return f}function parseGposTable(r,e,a){var s=new parse.Parser(r,e),t=s.parseFixed();check.argument(1===t,"Unsupported GPOS table version."),parseTaggedListTable(r,e+s.parseUShort()),parseTaggedListTable(r,e+s.parseUShort());var o=s.parseUShort();s.relativeOffset=o;for(var p=s.parseUShort(),n=s.parseOffset16List(p),f=e+o,i=0;p>i;i++){var h=parseLookupTable(r,f+n[i]);2!==h.lookupType||a.getGposKerningValue||(a.getGposKerningValue=h.getKerningValue)}}var check=require("../check"),parse=require("../parse");exports.parse=parseGposTable;
},{"../check":1,"../parse":7}],14:[function(require,module,exports){
"use strict";function parseHeadTable(e,a){var r={},t=new parse.Parser(e,a);return r.version=t.parseVersion(),r.fontRevision=Math.round(1e3*t.parseFixed())/1e3,r.checkSumAdjustment=t.parseULong(),r.magicNumber=t.parseULong(),check.argument(1594834165===r.magicNumber,"Font header has wrong magic number."),r.flags=t.parseUShort(),r.unitsPerEm=t.parseUShort(),r.created=t.parseLongDateTime(),r.modified=t.parseLongDateTime(),r.xMin=t.parseShort(),r.yMin=t.parseShort(),r.xMax=t.parseShort(),r.yMax=t.parseShort(),r.macStyle=t.parseUShort(),r.lowestRecPPEM=t.parseUShort(),r.fontDirectionHint=t.parseShort(),r.indexToLocFormat=t.parseShort(),r.glyphDataFormat=t.parseShort(),r}function makeHeadTable(e){return new table.Table("head",[{name:"version",type:"FIXED",value:65536},{name:"fontRevision",type:"FIXED",value:65536},{name:"checkSumAdjustment",type:"ULONG",value:0},{name:"magicNumber",type:"ULONG",value:1594834165},{name:"flags",type:"USHORT",value:0},{name:"unitsPerEm",type:"USHORT",value:1e3},{name:"created",type:"LONGDATETIME",value:0},{name:"modified",type:"LONGDATETIME",value:0},{name:"xMin",type:"SHORT",value:0},{name:"yMin",type:"SHORT",value:0},{name:"xMax",type:"SHORT",value:0},{name:"yMax",type:"SHORT",value:0},{name:"macStyle",type:"USHORT",value:0},{name:"lowestRecPPEM",type:"USHORT",value:0},{name:"fontDirectionHint",type:"SHORT",value:2},{name:"indexToLocFormat",type:"SHORT",value:0},{name:"glyphDataFormat",type:"SHORT",value:0}],e)}var check=require("../check"),parse=require("../parse"),table=require("../table");exports.parse=parseHeadTable,exports.make=makeHeadTable;
},{"../check":1,"../parse":7,"../table":9}],15:[function(require,module,exports){
"use strict";function parseHheaTable(e,a){var r={},t=new parse.Parser(e,a);return r.version=t.parseVersion(),r.ascender=t.parseShort(),r.descender=t.parseShort(),r.lineGap=t.parseShort(),r.advanceWidthMax=t.parseUShort(),r.minLeftSideBearing=t.parseShort(),r.minRightSideBearing=t.parseShort(),r.xMaxExtent=t.parseShort(),r.caretSlopeRise=t.parseShort(),r.caretSlopeRun=t.parseShort(),r.caretOffset=t.parseShort(),t.relativeOffset+=8,r.metricDataFormat=t.parseShort(),r.numberOfHMetrics=t.parseUShort(),r}function makeHheaTable(e){return new table.Table("hhea",[{name:"version",type:"FIXED",value:65536},{name:"ascender",type:"FWORD",value:0},{name:"descender",type:"FWORD",value:0},{name:"lineGap",type:"FWORD",value:0},{name:"advanceWidthMax",type:"UFWORD",value:0},{name:"minLeftSideBearing",type:"FWORD",value:0},{name:"minRightSideBearing",type:"FWORD",value:0},{name:"xMaxExtent",type:"FWORD",value:0},{name:"caretSlopeRise",type:"SHORT",value:1},{name:"caretSlopeRun",type:"SHORT",value:0},{name:"caretOffset",type:"SHORT",value:0},{name:"reserved1",type:"SHORT",value:0},{name:"reserved2",type:"SHORT",value:0},{name:"reserved3",type:"SHORT",value:0},{name:"reserved4",type:"SHORT",value:0},{name:"metricDataFormat",type:"SHORT",value:0},{name:"numberOfHMetrics",type:"USHORT",value:0}],e)}var parse=require("../parse"),table=require("../table");exports.parse=parseHheaTable,exports.make=makeHheaTable;
},{"../parse":7,"../table":9}],16:[function(require,module,exports){
"use strict";function parseHmtxTable(e,a,r,t,s){for(var i,l,n=new parse.Parser(e,a),p=0;t>p;p+=1){r>p&&(i=n.parseUShort(),l=n.parseShort());var d=s[p];d.advanceWidth=i,d.leftSideBearing=l}}function makeHmtxTable(e){for(var a=new table.Table("hmtx",[]),r=0;rn;n+=1){var h=s.parseUShort(),u=s.parseUShort(),c=s.parseShort();a[h+","+u]=c}return a}var check=require("../check"),parse=require("../parse");exports.parse=parseKernTable;
},{"../check":1,"../parse":7}],18:[function(require,module,exports){
"use strict";function parseLocaTable(r,a,e,s){for(var p=new parse.Parser(r,a),o=s?p.parseUShort:p.parseULong,t=[],c=0;e+1>c;c+=1){var n=o.call(p);s&&(n*=2),t.push(n)}return t}var parse=require("../parse");exports.parse=parseLocaTable;
},{"../parse":7}],19:[function(require,module,exports){
"use strict";function parseMaxpTable(e,a){var r={},s=new parse.Parser(e,a);return r.version=s.parseVersion(),r.numGlyphs=s.parseUShort(),1===r.version&&(r.maxPoints=s.parseUShort(),r.maxContours=s.parseUShort(),r.maxCompositePoints=s.parseUShort(),r.maxCompositeContours=s.parseUShort(),r.maxZones=s.parseUShort(),r.maxTwilightPoints=s.parseUShort(),r.maxStorage=s.parseUShort(),r.maxFunctionDefs=s.parseUShort(),r.maxInstructionDefs=s.parseUShort(),r.maxStackElements=s.parseUShort(),r.maxSizeOfInstructions=s.parseUShort(),r.maxComponentElements=s.parseUShort(),r.maxComponentDepth=s.parseUShort()),r}function makeMaxpTable(e){return new table.Table("maxp",[{name:"version",type:"FIXED",value:20480},{name:"numGlyphs",type:"USHORT",value:e}])}var parse=require("../parse"),table=require("../table");exports.parse=parseMaxpTable,exports.make=makeMaxpTable;
},{"../parse":7,"../table":9}],20:[function(require,module,exports){
"use strict";function parseNameTable(e,a){var r={},n=new parse.Parser(e,a);r.format=n.parseUShort();for(var t=n.parseUShort(),s=n.offset+n.parseUShort(),o=0,m=0;t>m;m++){var l=n.parseUShort(),p=n.parseUShort(),u=n.parseUShort(),i=n.parseUShort(),d=nameTableNames[i],c=n.parseUShort(),f=n.parseUShort();if(3===l&&1===p&&1033===u){for(var h=[],T=c/2,g=0;T>g;g++,f+=2)h[g]=parse.getShort(e,s+f);var S=String.fromCharCode.apply(null,h);d?r[d]=S:(o++,r["unknown"+o]=S)}}return 1===r.format&&(r.langTagCount=n.parseUShort()),r}function makeNameRecord(e,a,r,n,t,s){return new table.Table("NameRecord",[{name:"platformID",type:"USHORT",value:e},{name:"encodingID",type:"USHORT",value:a},{name:"languageID",type:"USHORT",value:r},{name:"nameID",type:"USHORT",value:n},{name:"length",type:"USHORT",value:t},{name:"offset",type:"USHORT",value:s}])}function addMacintoshNameRecord(e,a,r,n){var t=encode.STRING(r);return e.records.push(makeNameRecord(1,0,0,a,t.length,n)),e.strings.push(t),n+=t.length}function addWindowsNameRecord(e,a,r,n){var t=encode.UTF16(r);return e.records.push(makeNameRecord(3,1,1033,a,t.length,n)),e.strings.push(t),n+=t.length}function makeNameTable(e){var a=new table.Table("name",[{name:"format",type:"USHORT",value:0},{name:"count",type:"USHORT",value:0},{name:"stringOffset",type:"USHORT",value:0}]);a.records=[],a.strings=[];var r,n,t=0;for(r=0;r=a.begin&&et;t++)a.panose[t]=i.parseByte();return a.ulUnicodeRange1=i.parseULong(),a.ulUnicodeRange2=i.parseULong(),a.ulUnicodeRange3=i.parseULong(),a.ulUnicodeRange4=i.parseULong(),a.achVendID=String.fromCharCode(i.parseByte(),i.parseByte(),i.parseByte(),i.parseByte()),a.fsSelection=i.parseUShort(),a.usFirstCharIndex=i.parseUShort(),a.usLastCharIndex=i.parseUShort(),a.sTypoAscender=i.parseShort(),a.sTypoDescender=i.parseShort(),a.sTypoLineGap=i.parseShort(),a.usWinAscent=i.parseUShort(),a.usWinDescent=i.parseUShort(),a.version>=1&&(a.ulCodePageRange1=i.parseULong(),a.ulCodePageRange2=i.parseULong()),a.version>=2&&(a.sxHeight=i.parseShort(),a.sCapHeight=i.parseShort(),a.usDefaultChar=i.parseUShort(),a.usBreakChar=i.parseUShort(),a.usMaxContent=i.parseUShort()),a}function makeOS2Table(e){return new table.Table("OS/2",[{name:"version",type:"USHORT",value:3},{name:"xAvgCharWidth",type:"SHORT",value:0},{name:"usWeightClass",type:"USHORT",value:0},{name:"usWidthClass",type:"USHORT",value:0},{name:"fsType",type:"USHORT",value:0},{name:"ySubscriptXSize",type:"SHORT",value:650},{name:"ySubscriptYSize",type:"SHORT",value:699},{name:"ySubscriptXOffset",type:"SHORT",value:0},{name:"ySubscriptYOffset",type:"SHORT",value:140},{name:"ySuperscriptXSize",type:"SHORT",value:650},{name:"ySuperscriptYSize",type:"SHORT",value:699},{name:"ySuperscriptXOffset",type:"SHORT",value:0},{name:"ySuperscriptYOffset",type:"SHORT",value:479},{name:"yStrikeoutSize",type:"SHORT",value:49},{name:"yStrikeoutPosition",type:"SHORT",value:258},{name:"sFamilyClass",type:"SHORT",value:0},{name:"bFamilyType",type:"BYTE",value:0},{name:"bSerifStyle",type:"BYTE",value:0},{name:"bWeight",type:"BYTE",value:0},{name:"bProportion",type:"BYTE",value:0},{name:"bContrast",type:"BYTE",value:0},{name:"bStrokeVariation",type:"BYTE",value:0},{name:"bArmStyle",type:"BYTE",value:0},{name:"bLetterform",type:"BYTE",value:0},{name:"bMidline",type:"BYTE",value:0},{name:"bXHeight",type:"BYTE",value:0},{name:"ulUnicodeRange1",type:"ULONG",value:0},{name:"ulUnicodeRange2",type:"ULONG",value:0},{name:"ulUnicodeRange3",type:"ULONG",value:0},{name:"ulUnicodeRange4",type:"ULONG",value:0},{name:"achVendID",type:"CHARARRAY",value:"XXXX"},{name:"fsSelection",type:"USHORT",value:0},{name:"usFirstCharIndex",type:"USHORT",value:0},{name:"usLastCharIndex",type:"USHORT",value:0},{name:"sTypoAscender",type:"SHORT",value:0},{name:"sTypoDescender",type:"SHORT",value:0},{name:"sTypoLineGap",type:"SHORT",value:0},{name:"usWinAscent",type:"USHORT",value:0},{name:"usWinDescent",type:"USHORT",value:0},{name:"ulCodePageRange1",type:"ULONG",value:0},{name:"ulCodePageRange2",type:"ULONG",value:0},{name:"sxHeight",type:"SHORT",value:0},{name:"sCapHeight",type:"SHORT",value:0},{name:"usDefaultChar",type:"USHORT",value:0},{name:"usBreakChar",type:"USHORT",value:0},{name:"usMaxContext",type:"USHORT",value:0}],e)}var parse=require("../parse"),table=require("../table"),unicodeRanges=[{begin:0,end:127},{begin:128,end:255},{begin:256,end:383},{begin:384,end:591},{begin:592,end:687},{begin:688,end:767},{begin:768,end:879},{begin:880,end:1023},{begin:11392,end:11519},{begin:1024,end:1279},{begin:1328,end:1423},{begin:1424,end:1535},{begin:42240,end:42559},{begin:1536,end:1791},{begin:1984,end:2047},{begin:2304,end:2431},{begin:2432,end:2559},{begin:2560,end:2687},{begin:2688,end:2815},{begin:2816,end:2943},{begin:2944,end:3071},{begin:3072,end:3199},{begin:3200,end:3327},{begin:3328,end:3455},{begin:3584,end:3711},{begin:3712,end:3839},{begin:4256,end:4351},{begin:6912,end:7039},{begin:4352,end:4607},{begin:7680,end:7935},{begin:7936,end:8191},{begin:8192,end:8303},{begin:8304,end:8351},{begin:8352,end:8399},{begin:8400,end:8447},{begin:8448,end:8527},{begin:8528,end:8591},{begin:8592,end:8703},{begin:8704,end:8959},{begin:8960,end:9215},{begin:9216,end:9279},{begin:9280,end:9311},{begin:9312,end:9471},{begin:9472,end:9599},{begin:9600,end:9631},{begin:9632,end:9727},{begin:9728,end:9983},{begin:9984,end:10175},{begin:12288,end:12351},{begin:12352,end:12447},{begin:12448,end:12543},{begin:12544,end:12591},{begin:12592,end:12687},{begin:43072,end:43135},{begin:12800,end:13055},{begin:13056,end:13311},{begin:44032,end:55215},{begin:55296,end:57343},{begin:67840,end:67871},{begin:19968,end:40959},{begin:57344,end:63743},{begin:12736,end:12783},{begin:64256,end:64335},{begin:64336,end:65023},{begin:65056,end:65071},{begin:65040,end:65055},{begin:65104,end:65135},{begin:65136,end:65279},{begin:65280,end:65519},{begin:65520,end:65535},{begin:3840,end:4095},{begin:1792,end:1871},{begin:1920,end:1983},{begin:3456,end:3583},{begin:4096,end:4255},{begin:4608,end:4991},{begin:5024,end:5119},{begin:5120,end:5759},{begin:5760,end:5791},{begin:5792,end:5887},{begin:6016,end:6143},{begin:6144,end:6319},{begin:10240,end:10495},{begin:40960,end:42127},{begin:5888,end:5919},{begin:66304,end:66351},{begin:66352,end:66383},{begin:66560,end:66639},{begin:118784,end:119039},{begin:119808,end:120831},{begin:1044480,end:1048573},{begin:65024,end:65039},{begin:917504,end:917631},{begin:6400,end:6479},{begin:6480,end:6527},{begin:6528,end:6623},{begin:6656,end:6687},{begin:11264,end:11359},{begin:11568,end:11647},{begin:19904,end:19967},{begin:43008,end:43055},{begin:65536,end:65663},{begin:65856,end:65935},{begin:66432,end:66463},{begin:66464,end:66527},{begin:66640,end:66687},{begin:66688,end:66735},{begin:67584,end:67647},{begin:68096,end:68191},{begin:119552,end:119647},{begin:73728,end:74751},{begin:119648,end:119679},{begin:7040,end:7103},{begin:7168,end:7247},{begin:7248,end:7295},{begin:43136,end:43231},{begin:43264,end:43311},{begin:43312,end:43359},{begin:43520,end:43615},{begin:65936,end:65999},{begin:66e3,end:66047},{begin:66208,end:66271},{begin:127024,end:127135}];exports.unicodeRanges=unicodeRanges,exports.getUnicodeRange=getUnicodeRange,exports.parse=parseOS2Table,exports.make=makeOS2Table;
},{"../parse":7,"../table":9}],22:[function(require,module,exports){
"use strict";function parsePostTable(e,a){var r,n={},s=new parse.Parser(e,a);switch(n.version=s.parseVersion(),n.italicAngle=s.parseFixed(),n.underlinePosition=s.parseShort(),n.underlineThickness=s.parseShort(),n.isFixedPitch=s.parseULong(),n.minMemType42=s.parseULong(),n.maxMemType42=s.parseULong(),n.minMemType1=s.parseULong(),n.maxMemType1=s.parseULong(),n.version){case 1:n.names=encoding.standardNames.slice();break;case 2:for(n.numberOfGlyphs=s.parseUShort(),n.glyphNameIndex=new Array(n.numberOfGlyphs),r=0;r=encoding.standardNames.length){var p=s.parseChar();n.names.push(s.parseString(p))}break;case 2.5:for(n.numberOfGlyphs=s.parseUShort(),n.offset=new Array(n.numberOfGlyphs),r=0;ra.value.tag?1:-1}),a.fields=a.fields.concat(r),a.fields=a.fields.concat(t),a}function metricsForChar(e,a,n){for(var r=0;r0){var i=e.glyphs[t];return i.getMetrics()}}return n}function average(e){for(var a=0,n=0;ng||null===m)&&(m=g),g>u&&(u=g);var y=os2.getUnicodeRange(g);if(32>y)c|=1<y)h|=1<y)o|=1<y))throw new Error("Unicode ranges bits > 123 are reserved for internal usage");d|=1<=0&&255>=e,"Byte value should be between 0 and 255."),[e]},sizeOf.BYTE=constant(1),encode.CHAR=function(e){return[e.charCodeAt(0)]},sizeOf.BYTE=constant(1),encode.CHARARRAY=function(e){for(var n=[],o=0;o>8&255,255&e]},sizeOf.USHORT=constant(2),encode.SHORT=function(e){return e>=LIMIT16&&(e=-(2*LIMIT16-e)),[e>>8&255,255&e]},sizeOf.SHORT=constant(2),encode.UINT24=function(e){return[e>>16&255,e>>8&255,255&e]},sizeOf.UINT24=constant(3),encode.ULONG=function(e){return[e>>24&255,e>>16&255,e>>8&255,255&e]},sizeOf.ULONG=constant(4),encode.LONG=function(e){return e>=LIMIT32&&(e=-(2*LIMIT32-e)),[e>>24&255,e>>16&255,e>>8&255,255&e]},sizeOf.LONG=constant(4),encode.FIXED=encode.ULONG,sizeOf.FIXED=sizeOf.ULONG,encode.FWORD=encode.SHORT,sizeOf.FWORD=sizeOf.SHORT,encode.UFWORD=encode.USHORT,sizeOf.UFWORD=sizeOf.USHORT,encode.LONGDATETIME=function(){return[0,0,0,0,0,0,0,0]},sizeOf.LONGDATETIME=constant(8),encode.TAG=function(e){return check.argument(4===e.length,"Tag should be exactly 4 ASCII characters."),[e.charCodeAt(0),e.charCodeAt(1),e.charCodeAt(2),e.charCodeAt(3)]},sizeOf.TAG=constant(4),encode.Card8=encode.BYTE,sizeOf.Card8=sizeOf.BYTE,encode.Card16=encode.USHORT,sizeOf.Card16=sizeOf.USHORT,encode.OffSize=encode.BYTE,sizeOf.OffSize=sizeOf.BYTE,encode.SID=encode.USHORT,sizeOf.SID=sizeOf.USHORT,encode.NUMBER=function(e){return e>=-107&&107>=e?[e+139]:e>=108&&1131>=e?(e-=108,[(e>>8)+247,255&e]):e>=-1131&&-108>=e?(e=-e-108,[(e>>8)+251,255&e]):e>=-32768&&32767>=e?encode.NUMBER16(e):encode.NUMBER32(e)},sizeOf.NUMBER=function(e){return encode.NUMBER(e).length},encode.NUMBER16=function(e){return[28,e>>8&255,255&e]},sizeOf.NUMBER16=constant(2),encode.NUMBER32=function(e){return[29,e>>24&255,e>>16&255,e>>8&255,255&e]},sizeOf.NUMBER32=constant(4),encode.NAME=encode.CHARARRAY,sizeOf.NAME=sizeOf.CHARARRAY,encode.STRING=encode.CHARARRAY,sizeOf.STRING=sizeOf.CHARARRAY,encode.UTF16=function(e){for(var n=[],o=0;oc;c+=1){var r=parseInt(o[c],0),f=e[r];n=n.concat(encode.OPERAND(f.value,f.type)),n=n.concat(encode.OPERATOR(r))}return n},sizeOf.DICT=function(e){return encode.DICT(e).length},encode.OPERATOR=function(e){return 1200>e?[e]:[12,e-1200]},encode.OPERAND=function(e,n){var o=[];if(Array.isArray(n))for(var t=0;tt;t+=1){var c=e[t];n=n.concat(encode[c.type](c.value))}return wmm&&wmm.set(e,n),n},sizeOf.CHARSTRING=function(e){return encode.CHARSTRING(e).length},encode.OBJECT=function(e){var n=encode[e.type];return check.argument(void 0!==n,"No encoding function for type "+e.type),n(e.value)},encode.TABLE=function(e){for(var n=[],o=e.fields.length,t=0;o>t;t+=1){var c=e.fields[t],r=encode[c.type];check.argument(void 0!==r,"No encoding function for field type "+c.type);var f=e[c.name];void 0===f&&(f=c.value);var d=r(f);n=n.concat(d)}return n},encode.LITERAL=function(e){return e},sizeOf.LITERAL=function(e){return e.length},exports.decode=decode,exports.encode=encode,exports.sizeOf=sizeOf;
},{"./check":1}]},{},[6])(6)
});