in seriously.js [3089:3262]
SourceNode = function (hook, source, options) {
var opts = options || {},
flip = opts.flip === undefined ? true : opts.flip,
width = opts.width,
height = opts.height,
deferTexture = false,
that = this,
matchedType = false,
key,
plugin;
function sourcePlugin(hook, source, options, force) {
var p = seriousSources[hook];
if (p.definition) {
p = p.definition.call(that, source, options, force);
if (p) {
p = extend(extend({}, seriousSources[hook]), p);
} else {
return null;
}
}
return p;
}
function compareSource(source) {
return that.source === source;
}
Node.call(this);
if (hook && typeof hook !== 'string' || !source && source !== 0) {
if (!options || typeof options !== 'object') {
options = source;
}
source = hook;
}
if (typeof source === 'string' && isNaN(source)) {
source = getElement(source, ['canvas', 'img', 'video']);
}
// forced source type?
if (typeof hook === 'string' && seriousSources[hook]) {
plugin = sourcePlugin(hook, source, options, true);
if (plugin) {
this.hook = hook;
matchedType = true;
deferTexture = plugin.deferTexture;
this.plugin = plugin;
this.compare = plugin.compare;
this.checkDirty = plugin.checkDirty;
if (plugin.source) {
source = plugin.source;
}
}
}
//todo: could probably stand to re-work and re-indent this whole block now that we have plugins
if (!plugin && source instanceof HTMLElement) {
if (source.tagName === 'CANVAS') {
this.width = source.width;
this.height = source.height;
this.render = this.renderImageCanvas;
matchedType = true;
this.hook = 'canvas';
this.compare = compareSource;
} else if (source.tagName === 'IMG') {
this.width = source.naturalWidth || 1;
this.height = source.naturalHeight || 1;
if (!source.complete || !source.naturalWidth) {
deferTexture = true;
}
source.addEventListener('load', function () {
if (!that.isDestroyed) {
if (that.width !== source.naturalWidth || that.height !== source.naturalHeight) {
that.width = source.naturalWidth;
that.height = source.naturalHeight;
that.resize();
}
that.setDirty();
that.setReady();
}
}, true);
this.render = this.renderImageCanvas;
matchedType = true;
this.hook = 'image';
this.compare = compareSource;
}
} else if (!plugin && source instanceof WebGLTexture) {
if (gl && !gl.isTexture(source)) {
throw new Error('Not a valid WebGL texture.');
}
//different defaults
if (!isNaN(width)) {
if (isNaN(height)) {
height = width;
}
} else if (!isNaN(height)) {
width = height;
}/* else {
//todo: guess based on dimensions of target canvas
//throw new Error('Must specify width and height when using a WebGL texture as a source');
}*/
this.width = width;
this.height = height;
if (opts.flip === undefined) {
flip = false;
}
matchedType = true;
this.texture = source;
this.initialized = true;
this.hook = 'texture';
this.compare = compareSource;
//todo: if WebGLTexture source is from a different context render it and copy it over
this.render = function () {};
}
if (!matchedType && !plugin) {
for (key in seriousSources) {
if (seriousSources.hasOwnProperty(key) && seriousSources[key]) {
plugin = sourcePlugin(key, source, options, false);
if (plugin) {
this.hook = key;
matchedType = true;
deferTexture = plugin.deferTexture;
this.plugin = plugin;
this.compare = plugin.compare;
this.checkDirty = plugin.checkDirty;
if (plugin.source) {
source = plugin.source;
}
break;
}
}
}
}
if (!matchedType) {
throw new Error('Unknown source type');
}
this.source = source;
if (this.flip === undefined) {
this.flip = flip;
}
this.targets = [];
if (!deferTexture) {
that.setReady();
}
this.pub = new Source(this);
nodes.push(this);
nodesById[this.id] = this;
sources.push(this);
allSourcesByHook[this.hook].push(this);
if (sources.length && !rafId) {
renderDaemon();
}
};