Created
December 18, 2019 01:12
-
-
Save jseppi/f4849acacb3de34ee976d3a19ff967b0 to your computer and use it in GitHub Desktop.
Render font previews // source https://jsbin.com/lomovel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<title>Render font previews</title> | |
<meta | |
name="viewport" | |
content="initial-scale=1,maximum-scale=1,user-scalable=no" | |
/> | |
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.js"></script> | |
<link | |
href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.css" | |
rel="stylesheet" | |
/> | |
<link | |
href="https://api.mapbox.com/mapbox-assembly/v0.24.0/assembly.min.css" | |
rel="stylesheet" | |
/> | |
<script | |
async | |
defer | |
src="https://api.mapbox.com/mapbox-assembly/v0.24.0/assembly.js" | |
></script> | |
<style> | |
body { | |
margin: 0; | |
padding: 0; | |
background: #3e3e3e; | |
} | |
.preview-image { | |
border: 1px solid yellow; | |
display:block; | |
margin-top: 10px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="render_map_1" style="position:absolute;top:-200px;width:1200px; height: 120px; visibility: hidden;" class="border"></div> | |
<script id="jsbin-javascript"> | |
"use strict"; | |
function _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); } | |
mapboxgl.accessToken = "pk.eyJ1IjoianNlcHBpbWJ4IiwiYSI6ImNqbGU1ODdtMzBpZjUzcG1pMWJnaHB2aHgifQ.xGVwKUpyJ-S5iyaLq7GFLA"; | |
var owner = "jseppimbx"; | |
var renderMap1 = new mapboxgl.Map({ | |
container: "render_map_1", | |
center: [0.525, -0.025], | |
zoom: 9, | |
pitch: 0, | |
bearing: 0, | |
fadeDuration: 0, | |
preserveDrawingBuffer: true, | |
localIdeographFontFamily: false | |
}); | |
var renderMap1Busy = false; | |
function generateFontPreviewStyle(_ref) { | |
var owner = _ref.owner; | |
var name = _ref.name; | |
var text = _ref.text; | |
var color = _ref.color; | |
return { | |
version: 8, | |
glyphs: "mapbox://fonts/" + owner + "/{fontstack}/{range}.pbf", | |
sources: { | |
font: { | |
type: "geojson", | |
data: { | |
type: "FeatureCollection", | |
features: [{ | |
type: "Feature", | |
geometry: { | |
type: "Point", | |
coordinates: [0, 0] | |
}, | |
properties: {} | |
}] | |
} | |
} | |
}, | |
layers: [{ | |
id: "preview", | |
source: "font", | |
type: "symbol", | |
layout: { | |
"text-justify": "left", | |
"text-anchor": "left", | |
"text-field": text, | |
"text-font": [name], | |
"text-max-width": 800, | |
"text-size": 44, | |
"text-line-height": 8 // TODO: does this do anything? | |
}, | |
paint: { | |
"text-color": color, | |
"text-halo-color": color, | |
"text-halo-width": 0.3, | |
"text-halo-blur": 0 | |
} | |
}] | |
}; | |
} | |
// ***** redux-like stuff | |
var state = {}; | |
state.fontPreviewsToRender = new Set(); | |
state.renderedFontPreviews = {}; | |
function makeFontKey(name, color, text) { | |
return name + "^" + color + "^" + text; | |
} | |
function fontKeyToParams(key) { | |
var parts = key.split("^"); | |
return { | |
name: parts[0], | |
color: parts[1], | |
text: parts[2] | |
}; | |
} | |
function addFontPreviewToRender(name, color, text) { | |
var key = makeFontKey(name, color, text); | |
if (!state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.add(key); | |
} | |
} | |
function getFontPreviewsToRender() { | |
var paramsToRender = []; | |
state.fontPreviewsToRender.forEach(function (key) { | |
var params = fontKeyToParams(key); | |
paramsToRender.push(params); | |
}); | |
return paramsToRender; | |
} | |
function saveRenderedFontPreviewData(name, color, text, dataURL) { | |
var key = makeFontKey(name, color, text); | |
state.renderedFontPreviews[key] = dataURL; | |
if (state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender["delete"](key); | |
} | |
} | |
// ***** fake output helpers | |
function addImage(dataURL) { | |
var img = document.createElement("img"); | |
img.src = dataURL; | |
img.classList.add("preview-image"); | |
document.body.appendChild(img); | |
} | |
function doneGeneratingPreviews() { | |
for (key in state.renderedFontPreviews) { | |
addImage(state.renderedFontPreviews[key]); | |
} | |
} | |
function blob2canvas(canvas, blob) { | |
var img = new Img(); | |
var ctx = canvas.getContext("2d"); | |
img.onload = function () { | |
ctx.drawImage(img, 0, 0); | |
}; | |
img.src = blob; | |
} | |
function convertURIToImageData(URI) { | |
return new Promise(function (resolve, reject) { | |
if (URI == null) return reject(); | |
var canvas = document.createElement("canvas"), | |
context = canvas.getContext("2d"), | |
image = new Image(); | |
image.addEventListener("load", function () { | |
canvas.width = image.width; | |
canvas.height = image.height; | |
context.drawImage(image, 0, 0, canvas.width, canvas.height); | |
resolve(context.getImageData(0, 0, canvas.width, canvas.height)); | |
}, false); | |
image.src = URI; | |
}); | |
} | |
function trimCanvas(canvas) { | |
var context = canvas.getContext("2d"); | |
var topLeft = { | |
x: canvas.width, | |
y: canvas.height, | |
update: function update(x, y) { | |
this.x = Math.min(this.x, x); | |
this.y = Math.min(this.y, y); | |
} | |
}; | |
var bottomRight = { | |
x: 0, | |
y: 0, | |
update: function update(x, y) { | |
this.x = Math.max(this.x, x); | |
this.y = Math.max(this.y, y); | |
} | |
}; | |
var imageData = context.getImageData(0, 0, canvas.width, canvas.height); | |
for (var x = 0; x < canvas.width; x++) { | |
for (var y = 0; y < canvas.height; y++) { | |
var alpha = imageData.data[y * (canvas.width * 4) + x * 4 + 3]; | |
if (alpha !== 0) { | |
topLeft.update(x, y); | |
bottomRight.update(x, y); | |
} | |
} | |
} | |
var width = bottomRight.x - topLeft.x; | |
var height = bottomRight.y - topLeft.y; | |
var croppedCanvas = context.getImageData(topLeft.x, topLeft.y, width, height); | |
canvas.width = width; | |
canvas.height = height; | |
context.putImageData(croppedCanvas, 0, 0); | |
return canvas; | |
} | |
function trimWebglCanvas(webglCanvas, callback) { | |
// TODO: Eli says there is a webgl canvas method | |
// we could use to get its pixels instead of this | |
// (what I asumme is) hacky method of making a | |
// new img and setting its src. | |
// Probably context.readPixels | |
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/readPixels | |
// const glCtx = webglCanvas.getContext('webgl'); | |
// const pixels = new Uint8Array(webglCanvas.width * webglCanvas.height * 4); | |
// glCtx.readPixels(0, 0, webglCanvas.width, webglCanvas.height, glCtx.RGBA, glCtx.UNSIGNED_BYTE, pixels); | |
// console.log('---> pixels') | |
// console.log(pixels); | |
// const trimmed = trimPixels(pixels, webglCanvas.width, webglCanvas.height); | |
// callback(trimmed); | |
var tmpCanvas = document.createElement("canvas"); | |
tmpCanvas.width = webglCanvas.width; | |
tmpCanvas.height = webglCanvas.height; | |
var tmpCtx = tmpCanvas.getContext("2d"); | |
var img = new Image(); | |
img.onload = function () { | |
tmpCtx.drawImage(img, 0, 0); | |
var trimmed = trimCanvas(tmpCanvas); | |
callback(trimmed); | |
}; | |
img.src = webglCanvas.toDataURL(); | |
} | |
// ***** render component stuff | |
var demoFontsToRender = ["Komika Hand Bold Italic", "Komika Hand Bold", "Komika Hand Italic", "Komika Hand Regular", "Komika Parch Regular", "Komika Title - Axis Regular", "Komika Title - Kaps Regular", "Komika Title - Paint Regular", "Komika Title - Wide Regular", "Komika Title Regular"]; | |
var color = "#fff"; | |
demoFontsToRender.forEach(function (name) { | |
addFontPreviewToRender(name, color, name); | |
}); | |
// get initial list of job params | |
var initialJobParams = getFontPreviewsToRender(); | |
var i = 0; | |
var windowMethod = "requestAnimationFrame"; // requestAnimationFrame | |
function processRenderJobs(jobParams) { | |
if (i > 100) { | |
console.log("emergency brake"); | |
return; | |
} | |
if (renderMap1Busy) { | |
// requeue | |
window[windowMethod](function () { | |
return processRenderJobs(jobParams); | |
}); | |
return; | |
} | |
// else | |
renderMap1Busy = true; | |
var _jobParams = _toArray(jobParams); | |
var params = _jobParams[0]; | |
var remainingParams = _jobParams.slice(1); | |
var style = generateFontPreviewStyle({ | |
owner: owner, | |
name: params.name, | |
text: params.text, | |
color: params.color | |
}); | |
renderMap1.setStyle(style); | |
renderMap1.once("idle", function () { | |
trimWebglCanvas(renderMap1.getCanvas(), function (cropped) { | |
var dataURL = cropped.toDataURL(); | |
// Save the rendered image data into state | |
saveRenderedFontPreviewData(params.name, params.text, params.color, dataURL); | |
renderMap1Busy = false; | |
// we have more to process, so queue up the remaining | |
if (remainingParams.length) { | |
window[windowMethod](function () { | |
return processRenderJobs(remainingParams); | |
}); | |
} else { | |
doneGeneratingPreviews(); | |
} | |
}); | |
}); | |
} | |
window[windowMethod](function () { | |
return processRenderJobs(initialJobParams); | |
}); | |
</script> | |
<script id="jsbin-source-javascript" type="text/javascript">mapboxgl.accessToken = | |
"pk.eyJ1IjoianNlcHBpbWJ4IiwiYSI6ImNqbGU1ODdtMzBpZjUzcG1pMWJnaHB2aHgifQ.xGVwKUpyJ-S5iyaLq7GFLA"; | |
const owner = "jseppimbx"; | |
const renderMap1 = new mapboxgl.Map({ | |
container: "render_map_1", | |
center: [0.525, -0.025], | |
zoom: 9, | |
pitch: 0, | |
bearing: 0, | |
fadeDuration: 0, | |
preserveDrawingBuffer: true, | |
localIdeographFontFamily: false | |
}); | |
let renderMap1Busy = false; | |
function generateFontPreviewStyle({ owner, name, text, color }) { | |
return { | |
version: 8, | |
glyphs: `mapbox://fonts/${owner}/{fontstack}/{range}.pbf`, | |
sources: { | |
font: { | |
type: "geojson", | |
data: { | |
type: "FeatureCollection", | |
features: [ | |
{ | |
type: "Feature", | |
geometry: { | |
type: "Point", | |
coordinates: [0, 0] | |
}, | |
properties: {} | |
} | |
] | |
} | |
} | |
}, | |
layers: [ | |
{ | |
id: "preview", | |
source: "font", | |
type: "symbol", | |
layout: { | |
"text-justify": "left", | |
"text-anchor": "left", | |
"text-field": text, | |
"text-font": [name], | |
"text-max-width": 800, | |
"text-size": 44, | |
"text-line-height": 8 // TODO: does this do anything? | |
}, | |
paint: { | |
"text-color": color, | |
"text-halo-color": color, | |
"text-halo-width": 0.3, | |
"text-halo-blur": 0 | |
} | |
} | |
] | |
}; | |
} | |
// ***** redux-like stuff | |
const state = {}; | |
state.fontPreviewsToRender = new Set(); | |
state.renderedFontPreviews = {}; | |
function makeFontKey(name, color, text) { | |
return `${name}^${color}^${text}`; | |
} | |
function fontKeyToParams(key) { | |
const parts = key.split("^"); | |
return { | |
name: parts[0], | |
color: parts[1], | |
text: parts[2] | |
}; | |
} | |
function addFontPreviewToRender(name, color, text) { | |
const key = makeFontKey(name, color, text); | |
if (!state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.add(key); | |
} | |
} | |
function getFontPreviewsToRender() { | |
const paramsToRender = []; | |
state.fontPreviewsToRender.forEach(key => { | |
const params = fontKeyToParams(key); | |
paramsToRender.push(params); | |
}); | |
return paramsToRender; | |
} | |
function saveRenderedFontPreviewData(name, color, text, dataURL) { | |
const key = makeFontKey(name, color, text); | |
state.renderedFontPreviews[key] = dataURL; | |
if (state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.delete(key); | |
} | |
} | |
// ***** fake output helpers | |
function addImage(dataURL) { | |
const img = document.createElement("img"); | |
img.src = dataURL; | |
img.classList.add("preview-image"); | |
document.body.appendChild(img); | |
} | |
function doneGeneratingPreviews() { | |
for (key in state.renderedFontPreviews) { | |
addImage(state.renderedFontPreviews[key]); | |
} | |
} | |
function blob2canvas(canvas, blob) { | |
var img = new Img(); | |
var ctx = canvas.getContext("2d"); | |
img.onload = function() { | |
ctx.drawImage(img, 0, 0); | |
}; | |
img.src = blob; | |
} | |
function convertURIToImageData(URI) { | |
return new Promise(function(resolve, reject) { | |
if (URI == null) return reject(); | |
var canvas = document.createElement("canvas"), | |
context = canvas.getContext("2d"), | |
image = new Image(); | |
image.addEventListener( | |
"load", | |
function() { | |
canvas.width = image.width; | |
canvas.height = image.height; | |
context.drawImage(image, 0, 0, canvas.width, canvas.height); | |
resolve(context.getImageData(0, 0, canvas.width, canvas.height)); | |
}, | |
false | |
); | |
image.src = URI; | |
}); | |
} | |
function trimCanvas(canvas) { | |
const context = canvas.getContext("2d"); | |
const topLeft = { | |
x: canvas.width, | |
y: canvas.height, | |
update(x, y) { | |
this.x = Math.min(this.x, x); | |
this.y = Math.min(this.y, y); | |
} | |
}; | |
const bottomRight = { | |
x: 0, | |
y: 0, | |
update(x, y) { | |
this.x = Math.max(this.x, x); | |
this.y = Math.max(this.y, y); | |
} | |
}; | |
const imageData = context.getImageData(0, 0, canvas.width, canvas.height); | |
for (let x = 0; x < canvas.width; x++) { | |
for (let y = 0; y < canvas.height; y++) { | |
const alpha = imageData.data[y * (canvas.width * 4) + x * 4 + 3]; | |
if (alpha !== 0) { | |
topLeft.update(x, y); | |
bottomRight.update(x, y); | |
} | |
} | |
} | |
const width = bottomRight.x - topLeft.x; | |
const height = bottomRight.y - topLeft.y; | |
const croppedCanvas = context.getImageData( | |
topLeft.x, | |
topLeft.y, | |
width, | |
height | |
); | |
canvas.width = width; | |
canvas.height = height; | |
context.putImageData(croppedCanvas, 0, 0); | |
return canvas; | |
} | |
function trimWebglCanvas(webglCanvas, callback) { | |
// TODO: Eli says there is a webgl canvas method | |
// we could use to get its pixels instead of this | |
// (what I asumme is) hacky method of making a | |
// new img and setting its src. | |
// Probably context.readPixels | |
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/readPixels | |
// const glCtx = webglCanvas.getContext('webgl'); | |
// const pixels = new Uint8Array(webglCanvas.width * webglCanvas.height * 4); | |
// glCtx.readPixels(0, 0, webglCanvas.width, webglCanvas.height, glCtx.RGBA, glCtx.UNSIGNED_BYTE, pixels); | |
// console.log('---> pixels') | |
// console.log(pixels); | |
// const trimmed = trimPixels(pixels, webglCanvas.width, webglCanvas.height); | |
// callback(trimmed); | |
const tmpCanvas = document.createElement("canvas"); | |
tmpCanvas.width = webglCanvas.width; | |
tmpCanvas.height = webglCanvas.height; | |
const tmpCtx = tmpCanvas.getContext("2d"); | |
const img = new Image(); | |
img.onload = () => { | |
tmpCtx.drawImage(img, 0, 0); | |
const trimmed = trimCanvas(tmpCanvas); | |
callback(trimmed); | |
}; | |
img.src = webglCanvas.toDataURL(); | |
} | |
// ***** render component stuff | |
const demoFontsToRender = [ | |
"Komika Hand Bold Italic", | |
"Komika Hand Bold", | |
"Komika Hand Italic", | |
"Komika Hand Regular", | |
"Komika Parch Regular", | |
"Komika Title - Axis Regular", | |
"Komika Title - Kaps Regular", | |
"Komika Title - Paint Regular", | |
"Komika Title - Wide Regular", | |
"Komika Title Regular" | |
]; | |
const color = "#fff"; | |
demoFontsToRender.forEach(name => { | |
addFontPreviewToRender(name, color, name); | |
}); | |
// get initial list of job params | |
const initialJobParams = getFontPreviewsToRender(); | |
let i = 0; | |
const windowMethod = "requestAnimationFrame"; // requestAnimationFrame | |
function processRenderJobs(jobParams) { | |
if (i > 100) { | |
console.log("emergency brake"); | |
return; | |
} | |
if (renderMap1Busy) { | |
// requeue | |
window[windowMethod](() => processRenderJobs(jobParams)); | |
return; | |
} | |
// else | |
renderMap1Busy = true; | |
const [params, ...remainingParams] = jobParams; | |
const style = generateFontPreviewStyle({ | |
owner, | |
name: params.name, | |
text: params.text, | |
color: params.color | |
}); | |
renderMap1.setStyle(style); | |
renderMap1.once("idle", () => { | |
trimWebglCanvas(renderMap1.getCanvas(), cropped => { | |
const dataURL = cropped.toDataURL(); | |
// Save the rendered image data into state | |
saveRenderedFontPreviewData( | |
params.name, | |
params.text, | |
params.color, | |
dataURL | |
); | |
renderMap1Busy = false; | |
// we have more to process, so queue up the remaining | |
if (remainingParams.length) { | |
window[windowMethod](() => processRenderJobs(remainingParams)); | |
} else { | |
doneGeneratingPreviews(); | |
} | |
}); | |
}); | |
} | |
window[windowMethod](() => processRenderJobs(initialJobParams)); | |
</script></body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
function _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); } | |
mapboxgl.accessToken = "pk.eyJ1IjoianNlcHBpbWJ4IiwiYSI6ImNqbGU1ODdtMzBpZjUzcG1pMWJnaHB2aHgifQ.xGVwKUpyJ-S5iyaLq7GFLA"; | |
var owner = "jseppimbx"; | |
var renderMap1 = new mapboxgl.Map({ | |
container: "render_map_1", | |
center: [0.525, -0.025], | |
zoom: 9, | |
pitch: 0, | |
bearing: 0, | |
fadeDuration: 0, | |
preserveDrawingBuffer: true, | |
localIdeographFontFamily: false | |
}); | |
var renderMap1Busy = false; | |
function generateFontPreviewStyle(_ref) { | |
var owner = _ref.owner; | |
var name = _ref.name; | |
var text = _ref.text; | |
var color = _ref.color; | |
return { | |
version: 8, | |
glyphs: "mapbox://fonts/" + owner + "/{fontstack}/{range}.pbf", | |
sources: { | |
font: { | |
type: "geojson", | |
data: { | |
type: "FeatureCollection", | |
features: [{ | |
type: "Feature", | |
geometry: { | |
type: "Point", | |
coordinates: [0, 0] | |
}, | |
properties: {} | |
}] | |
} | |
} | |
}, | |
layers: [{ | |
id: "preview", | |
source: "font", | |
type: "symbol", | |
layout: { | |
"text-justify": "left", | |
"text-anchor": "left", | |
"text-field": text, | |
"text-font": [name], | |
"text-max-width": 800, | |
"text-size": 44, | |
"text-line-height": 8 // TODO: does this do anything? | |
}, | |
paint: { | |
"text-color": color, | |
"text-halo-color": color, | |
"text-halo-width": 0.3, | |
"text-halo-blur": 0 | |
} | |
}] | |
}; | |
} | |
// ***** redux-like stuff | |
var state = {}; | |
state.fontPreviewsToRender = new Set(); | |
state.renderedFontPreviews = {}; | |
function makeFontKey(name, color, text) { | |
return name + "^" + color + "^" + text; | |
} | |
function fontKeyToParams(key) { | |
var parts = key.split("^"); | |
return { | |
name: parts[0], | |
color: parts[1], | |
text: parts[2] | |
}; | |
} | |
function addFontPreviewToRender(name, color, text) { | |
var key = makeFontKey(name, color, text); | |
if (!state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.add(key); | |
} | |
} | |
function getFontPreviewsToRender() { | |
var paramsToRender = []; | |
state.fontPreviewsToRender.forEach(function (key) { | |
var params = fontKeyToParams(key); | |
paramsToRender.push(params); | |
}); | |
return paramsToRender; | |
} | |
function saveRenderedFontPreviewData(name, color, text, dataURL) { | |
var key = makeFontKey(name, color, text); | |
state.renderedFontPreviews[key] = dataURL; | |
if (state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender["delete"](key); | |
} | |
} | |
// ***** fake output helpers | |
function addImage(dataURL) { | |
var img = document.createElement("img"); | |
img.src = dataURL; | |
img.classList.add("preview-image"); | |
document.body.appendChild(img); | |
} | |
function doneGeneratingPreviews() { | |
for (key in state.renderedFontPreviews) { | |
addImage(state.renderedFontPreviews[key]); | |
} | |
} | |
function blob2canvas(canvas, blob) { | |
var img = new Img(); | |
var ctx = canvas.getContext("2d"); | |
img.onload = function () { | |
ctx.drawImage(img, 0, 0); | |
}; | |
img.src = blob; | |
} | |
function convertURIToImageData(URI) { | |
return new Promise(function (resolve, reject) { | |
if (URI == null) return reject(); | |
var canvas = document.createElement("canvas"), | |
context = canvas.getContext("2d"), | |
image = new Image(); | |
image.addEventListener("load", function () { | |
canvas.width = image.width; | |
canvas.height = image.height; | |
context.drawImage(image, 0, 0, canvas.width, canvas.height); | |
resolve(context.getImageData(0, 0, canvas.width, canvas.height)); | |
}, false); | |
image.src = URI; | |
}); | |
} | |
function trimCanvas(canvas) { | |
var context = canvas.getContext("2d"); | |
var topLeft = { | |
x: canvas.width, | |
y: canvas.height, | |
update: function update(x, y) { | |
this.x = Math.min(this.x, x); | |
this.y = Math.min(this.y, y); | |
} | |
}; | |
var bottomRight = { | |
x: 0, | |
y: 0, | |
update: function update(x, y) { | |
this.x = Math.max(this.x, x); | |
this.y = Math.max(this.y, y); | |
} | |
}; | |
var imageData = context.getImageData(0, 0, canvas.width, canvas.height); | |
for (var x = 0; x < canvas.width; x++) { | |
for (var y = 0; y < canvas.height; y++) { | |
var alpha = imageData.data[y * (canvas.width * 4) + x * 4 + 3]; | |
if (alpha !== 0) { | |
topLeft.update(x, y); | |
bottomRight.update(x, y); | |
} | |
} | |
} | |
var width = bottomRight.x - topLeft.x; | |
var height = bottomRight.y - topLeft.y; | |
var croppedCanvas = context.getImageData(topLeft.x, topLeft.y, width, height); | |
canvas.width = width; | |
canvas.height = height; | |
context.putImageData(croppedCanvas, 0, 0); | |
return canvas; | |
} | |
function trimWebglCanvas(webglCanvas, callback) { | |
// TODO: Eli says there is a webgl canvas method | |
// we could use to get its pixels instead of this | |
// (what I asumme is) hacky method of making a | |
// new img and setting its src. | |
// Probably context.readPixels | |
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/readPixels | |
// const glCtx = webglCanvas.getContext('webgl'); | |
// const pixels = new Uint8Array(webglCanvas.width * webglCanvas.height * 4); | |
// glCtx.readPixels(0, 0, webglCanvas.width, webglCanvas.height, glCtx.RGBA, glCtx.UNSIGNED_BYTE, pixels); | |
// console.log('---> pixels') | |
// console.log(pixels); | |
// const trimmed = trimPixels(pixels, webglCanvas.width, webglCanvas.height); | |
// callback(trimmed); | |
var tmpCanvas = document.createElement("canvas"); | |
tmpCanvas.width = webglCanvas.width; | |
tmpCanvas.height = webglCanvas.height; | |
var tmpCtx = tmpCanvas.getContext("2d"); | |
var img = new Image(); | |
img.onload = function () { | |
tmpCtx.drawImage(img, 0, 0); | |
var trimmed = trimCanvas(tmpCanvas); | |
callback(trimmed); | |
}; | |
img.src = webglCanvas.toDataURL(); | |
} | |
// ***** render component stuff | |
var demoFontsToRender = ["Komika Hand Bold Italic", "Komika Hand Bold", "Komika Hand Italic", "Komika Hand Regular", "Komika Parch Regular", "Komika Title - Axis Regular", "Komika Title - Kaps Regular", "Komika Title - Paint Regular", "Komika Title - Wide Regular", "Komika Title Regular"]; | |
var color = "#fff"; | |
demoFontsToRender.forEach(function (name) { | |
addFontPreviewToRender(name, color, name); | |
}); | |
// get initial list of job params | |
var initialJobParams = getFontPreviewsToRender(); | |
var i = 0; | |
var windowMethod = "requestAnimationFrame"; // requestAnimationFrame | |
function processRenderJobs(jobParams) { | |
if (i > 100) { | |
console.log("emergency brake"); | |
return; | |
} | |
if (renderMap1Busy) { | |
// requeue | |
window[windowMethod](function () { | |
return processRenderJobs(jobParams); | |
}); | |
return; | |
} | |
// else | |
renderMap1Busy = true; | |
var _jobParams = _toArray(jobParams); | |
var params = _jobParams[0]; | |
var remainingParams = _jobParams.slice(1); | |
var style = generateFontPreviewStyle({ | |
owner: owner, | |
name: params.name, | |
text: params.text, | |
color: params.color | |
}); | |
renderMap1.setStyle(style); | |
renderMap1.once("idle", function () { | |
trimWebglCanvas(renderMap1.getCanvas(), function (cropped) { | |
var dataURL = cropped.toDataURL(); | |
// Save the rendered image data into state | |
saveRenderedFontPreviewData(params.name, params.text, params.color, dataURL); | |
renderMap1Busy = false; | |
// we have more to process, so queue up the remaining | |
if (remainingParams.length) { | |
window[windowMethod](function () { | |
return processRenderJobs(remainingParams); | |
}); | |
} else { | |
doneGeneratingPreviews(); | |
} | |
}); | |
}); | |
} | |
window[windowMethod](function () { | |
return processRenderJobs(initialJobParams); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment