Skip to content

Commit

Permalink
Simplify by using texImage2D/texSubImage2D for any context
Browse files Browse the repository at this point in the history
(Enables removal of dimensions and secondary _canvas)
  • Loading branch information
Lauren Budorick committed Jan 5, 2017
1 parent f493f12 commit 773993f
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 78 deletions.
87 changes: 30 additions & 57 deletions js/source/canvas_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ const window = require('../util/window');
* [-76.52, 39.18],
* [-76.52, 39.17],
* [-76.54, 39.17]
* ],
* dimensions: [0, 0, 400, 400]
* ]
* });
*
* // update
Expand All @@ -31,10 +30,6 @@ const window = require('../util/window');
* [-76.54520273208618, 39.17876344106642]
* ]);
*
* // update
* var mySource = map.getSource('some id');
* mySource.setDimensions([0, 0, 600, 600]);
*
* map.removeSource('some id'); // remove
* @see [Add a canvas (TODO: this page does not yet exist)](https://www.mapbox.com/mapbox-gl-js/example/canvas-on-a-map/)
*/
Expand All @@ -44,53 +39,27 @@ class CanvasSource extends ImageSource {
super(id, options, dispatcher, eventedParent);
this.options = options;
this.animate = options.hasOwnProperty('animate') ? options.animate : true;
this.dimensions = options.dimensions;
this.resize = false;
}

load() {
this._canvas = this._canvas || window.document.getElementById(this.options.canvas);

// detect context type
if (this._canvas.getContext('2d')) {
this.contextType = '2d';
this.canvas = this._canvas;
} else if (this._canvas.getContext('webgl')) {
this.contextType = 'webgl';
}
this.canvas = this.canvas || window.document.getElementById(this.options.canvas);
this.width = this.canvas.width;
this.height = this.canvas.height;
if (this._hasInvalidDimensions(this.canvas)) return this.fire('error', new Error('Canvas dimensions cannot be less than or equal to zero.'));

this._rereadCanvas();
let loopID;

this.play = function() {
this.map.style.animationLoop.set(Infinity);
loopID = this.map.style.animationLoop.set(Infinity);
this.map._rerender();
};

this._finishLoading();
}

_rereadCanvas() {
if (!this.animate && this.canvas) return;

if (this.contextType === 'webgl') {
if (this.canvasBuffer) delete this.canvasBuffer;

const w = this.dimensions[2] - this.dimensions[0],
h = this.dimensions[3] - this.dimensions[1];

this.canvasBuffer = new Uint8Array(w * h * 4);

const ctx = this.canvas.getContext('webgl');

ctx.readPixels(
this.dimensions[0],
this.dimensions[1],
this.dimensions[2],
this.dimensions[3],
ctx.RGBA, ctx.UNSIGNED_BYTE, this.canvasBuffer);
this.canvas = new window.ImageData(new Uint8ClampedArray(this.canvasBuffer), w, h);
}
this.pause = function() {
this.map.style.animationLoop.cancel(loopID);
};

this._finishLoading();
}

/**
Expand All @@ -99,7 +68,7 @@ class CanvasSource extends ImageSource {
* @returns {HTMLCanvasElement} The HTML `canvas` element.
*/
getCanvas() {
return this._canvas;
return this.canvas;
}

onAdd(map) {
Expand All @@ -125,32 +94,36 @@ class CanvasSource extends ImageSource {
// setCoordinates inherited from ImageSource

prepare() {
if (!this.tile) return; // not enough data for current position
if (this.canvas.width !== this.width) {
this.width = this.canvas.width;
this.resize = true;
}
if (this.canvas.height !== this.height) {
this.height = this.canvas.height;
this.resize = true;
}
if (this._hasInvalidDimensions()) {
return this.fire('error', new Error('Canvas dimensions cannot be less than or equal to zero.'));
}

this._rereadCanvas();
if (!this.tile) return; // not enough data for current position
this._prepareImage(this.map.painter.gl, this.canvas, this.resize);
this.resize = false;
}

serialize() {
return {
type: 'canvas',
canvas: this._canvas,
canvas: this.canvas,
coordinates: this.coordinates
};
}

/**
* Sets new dimensions to read the canvas and re-renders the map.
* @method setDimensions
* @param {Array<Array<number>>} dimensions Four pixel dimensions,
* represented as an array of [x (first horizontal pixel), y (first
* vertical pixel), width, height].
*/
setDimensions(dimensions) {
this.dimensions = dimensions;
this._rereadCanvas();
this.resize = true;
_hasInvalidDimensions() {
for (const x of [this.canvas.width, this.canvas.height]) {
if (isNaN(x) || x <= 0) return true;
}
return false;
}
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"geojson-vt": "^2.4.0",
"grid-index": "^1.0.0",
"mapbox-gl-function": "mapbox/mapbox-gl-function#41c6724e2bbd7bd1eb5991451bbf118b7d02b525",
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#c4ac63cb1b8cd8af185319ae9d071047c1537f09",
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#2a79555803a0515fe517879ee7250f87bf3e425d",
"mapbox-gl-supported": "^1.2.0",
"package-json-versionify": "^1.0.2",
"pbf": "^1.3.2",
Expand Down
22 changes: 2 additions & 20 deletions test/js/source/canvas_source.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ function createSource(options) {

options = util.extend({
canvas: 'id',
coordinates: [[0, 0], [1, 0], [1, 1], [0, 1]],
dimensions: [0, 0, 20, 20]
coordinates: [[0, 0], [1, 0], [1, 1], [0, 1]]
}, options);

const source = new CanvasSource('id', options, { send: function() {} }, options.eventedParent);

source._canvas = c;
source.canvas = c;

return source;
}
Expand Down Expand Up @@ -52,7 +51,6 @@ test('CanvasSource', (t) => {
t.equal(source.minzoom, 0);
t.equal(source.maxzoom, 22);
t.equal(source.tileSize, 512);
t.equal(source.contextType, '2d');
t.equal(source.animate, true);
t.equal(typeof source.play, 'function');
t.end();
Expand Down Expand Up @@ -107,19 +105,3 @@ test('CanvasSource#serialize', (t) => {

t.end();
});

test('CanvasSource#setDimensions', (t) => {
const source = createSource();

t.equal(source.resize, false);
t.deepEqual(source.dimensions, [0, 0, 20, 20]);

source.setDimensions([0, 0, 30, 30]);

t.equal(source.resize, true);
t.deepEqual(source.dimensions, [0, 0, 30, 30]);

window.restore();

t.end();
});

0 comments on commit 773993f

Please sign in to comment.