From 06f6ba13c888242168c23c3ca1c97b8962e5a055 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Mon, 16 Mar 2020 23:23:34 +0100 Subject: [PATCH] Make font loading work in workers --- src/ol/css.js | 27 ++++++++++++------------ src/ol/render/canvas.js | 46 ++++++++++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/ol/css.js b/src/ol/css.js index c855fae7ea..f4eb09eb59 100644 --- a/src/ol/css.js +++ b/src/ol/css.js @@ -7,6 +7,7 @@ * @property {Array} families * @property {string} style * @property {string} weight + * @property {string} lineHeight */ @@ -68,8 +69,9 @@ export const CLASS_COLLAPSED = 'ol-collapsed'; /** * Get the list of font families from a font spec. Note that this doesn't work * for font families that have commas in them. - * @param {string} The CSS font property. - * @return {FontParameters} The font families (or null if the input spec is invalid). + * @param {string} fontSpec The CSS font property. + * @param {function(FontParameters):void} callback Called with the font families + * (or null if the input spec is invalid). */ export const getFontParameters = (function() { /** @@ -80,26 +82,25 @@ export const getFontParameters = (function() { * @type {Object} */ const cache = {}; - return function(font) { + return function(fontSpec, callback) { if (!style) { style = document.createElement('div').style; } - if (!(font in cache)) { - style.font = font; + if (!(fontSpec in cache)) { + style.font = fontSpec; const family = style.fontFamily; - const fontWeight = style.fontWeight; - const fontStyle = style.fontStyle; - style.font = ''; if (!family) { - return null; + callback(null); } const families = family.split(/,\s?/); - cache[font] = { + cache[fontSpec] = { families: families, - weight: fontWeight, - style: fontStyle + weight: style.fontWeight, + style: style.fontStyle, + lineHeight: style.lineHeight }; + style.font = ''; } - return cache[font]; + callback(cache[fontSpec]); }; })(); diff --git a/src/ol/render/canvas.js b/src/ol/render/canvas.js index 04781b9bc1..1a5293bd2e 100644 --- a/src/ol/render/canvas.js +++ b/src/ol/render/canvas.js @@ -266,8 +266,7 @@ export const registerFont = (function() { } } - return function(fontSpec) { - const font = getFontParameters(fontSpec); + function fontCallback(font) { if (!font) { return; } @@ -285,6 +284,31 @@ export const registerFont = (function() { } } } + } + + return function(fontSpec) { + if (WINDOW) { + getFontParameters(fontSpec, fontCallback); + } else { + /** @type {any} */ + const worker = self; + worker.postMessage({ + type: 'getFontParameters', + font: fontSpec + }); + worker.addEventListener('message', function handler(event) { + if (event.data.type === 'getFontParameters') { + worker.removeEventListener('message', handler); + const font = event.data.font; + fontCallback(font); + if (!textHeights[fontSpec]) { + const metrics = measureText(fontSpec, 'Žg'); + const lineHeight = isNaN(font.lineHeight) ? 1.2 : Number(font.lineHeight); + textHeights[fontSpec] = lineHeight * (metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent); + } + } + }); + } }; })(); @@ -320,13 +344,12 @@ export const measureTextHeight = (function() { }; })(); - /** * @param {string} font Font. * @param {string} text Text. - * @return {number} Width. + * @return {TextMetrics} Text metrics. */ -export function measureTextWidth(font, text) { +function measureText(font, text) { if (!measureContext) { measureContext = createCanvasContext2D(1, 1); } @@ -334,7 +357,16 @@ export function measureTextWidth(font, text) { measureContext.font = font; measureFont = measureContext.font; } - return measureContext.measureText(text).width; + return measureContext.measureText(text); +} + +/** + * @param {string} font Font. + * @param {string} text Text. + * @return {number} Width. + */ +export function measureTextWidth(font, text) { + return measureText(font, text).width; } @@ -434,7 +466,7 @@ function executeLabelInstructions(label, context) { const contextInstructions = label.contextInstructions; for (let i = 0, ii = contextInstructions.length; i < ii; i += 2) { if (Array.isArray(contextInstructions[i + 1])) { - CanvasRenderingContext2D.prototype[contextInstructions[i]].apply(context, contextInstructions[i + 1]); + context[contextInstructions[i]].apply(context, contextInstructions[i + 1]); } else { context[contextInstructions[i]] = contextInstructions[i + 1]; }