TinySDF = {
function TinySDF(size, buffer, value, radius, cutoff) {
this.fontSize = size;
this.buffer = buffer === undefined ? 3 : buffer;
this.cutoff = cutoff || 0.25;
this.radius = radius || 20;
var size = this.size = this.fontSize + this.buffer * 2;
this.canvas = document.createElement('canvas');
this.canvas.width = this.canvas.height = size;
this.circleWidth = this.canvas.width-10;
this.ctx = this.canvas.getContext('2d');
this.ctx.fillStyle = 'black';
this.gridOuter = new Float64Array(size * size);
this.gridInner = new Float64Array(size * size);
this.f = new Float64Array(size);
this.z = new Float64Array(size + 1);
this.v = new Uint16Array(size);
this.middle = Math.round((size / 2) * (navigator.userAgent.indexOf('Gecko/') >= 0 ? 1.2 : 1));
}
TinySDF.prototype.draw = function (char) {
this.ctx.arc(this.circleWidth/2, this.circleWidth/2, this.circleWidth/8, 0, 2 * Math.PI);
this.ctx.fill();
var imgData = this.ctx.getImageData(0, 0, this.size, this.size);
var alphaChannel = new Uint8ClampedArray(this.size * this.size);
for (var i = 0; i < this.size * this.size; i++) {
var a = imgData.data[i * 4 + 3] / 255;
this.gridOuter[i] = a === 1 ? 0 : a === 0 ? INF : Math.pow(Math.max(0, 0.5 - a), 2);
this.gridInner[i] = a === 1 ? INF : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2);
}
this.edt(this.gridOuter, this.size, this.size, this.f, this.v, this.z);
this.edt(this.gridInner, this.size, this.size, this.f, this.v, this.z);
for (i = 0; i < this.size * this.size; i++) {
var d = Math.sqrt(this.gridOuter[i]) - Math.sqrt(this.gridInner[i]);
alphaChannel[i] = Math.round(255 - 255 * (d / this.radius + this.cutoff));
}
this.alphaChannel = alphaChannel;
return alphaChannel;
}
TinySDF.prototype.edt = function (data, width, height, f, v, z) {
for (var x = 0; x < width; x++) this.edt1d(data, x, width, height, f, v, z);
for (var y = 0; y < height; y++) this.edt1d(data, y * width, 1, width, f, v, z);
}
TinySDF.prototype.edt1d = function (grid, offset, stride, length, f, v, z) {
var q, k, s, r;
v[0] = 0;
z[0] = -INF;
z[1] = INF;
for (q = 0; q < length; q++) f[q] = grid[offset + q * stride];
for (q = 1, k = 0, s = 0; q < length; q++) {
do {
r = v[k];
s = (f[q] - f[r] + q * q - r * r) / (q - r) / 2;
} while (s <= z[k] && --k > -1);
k++;
v[k] = q;
z[k] = s;
z[k + 1] = INF;
}
for (q = 0, k = 0; q < length; q++) {
while (z[k + 1] < q) k++;
r = v[k];
grid[offset + q * stride] = f[r] + (q - r) * (q - r);
}
}
return TinySDF;
}