Avoid try/catch, DOM and workers
This commit is contained in:
+46
-33
@@ -4,10 +4,13 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} FontParameters
|
* @typedef {Object} FontParameters
|
||||||
* @property {Array<string>} families
|
|
||||||
* @property {string} style
|
* @property {string} style
|
||||||
|
* @property {string} variant
|
||||||
* @property {string} weight
|
* @property {string} weight
|
||||||
|
* @property {string} size
|
||||||
* @property {string} lineHeight
|
* @property {string} lineHeight
|
||||||
|
* @property {string} family
|
||||||
|
* @property {Array<string>} families
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -65,42 +68,52 @@ export const CLASS_CONTROL = 'ol-control';
|
|||||||
*/
|
*/
|
||||||
export const CLASS_COLLAPSED = 'ol-collapsed';
|
export const CLASS_COLLAPSED = 'ol-collapsed';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From http://stackoverflow.com/questions/10135697/regex-to-parse-any-css-font
|
||||||
|
* @type {RegExp}
|
||||||
|
*/
|
||||||
|
const fontRegEx = new RegExp([
|
||||||
|
'^\\s*(?=(?:(?:[-a-z]+\\s*){0,2}(italic|oblique))?)',
|
||||||
|
'(?=(?:(?:[-a-z]+\\s*){0,2}(small-caps))?)',
|
||||||
|
'(?=(?:(?:[-a-z]+\\s*){0,2}(bold(?:er)?|lighter|[1-9]00 ))?)',
|
||||||
|
'(?:(?:normal|\\1|\\2|\\3)\\s*){0,3}((?:xx?-)?',
|
||||||
|
'(?:small|large)|medium|smaller|larger|[\\.\\d]+(?:\\%|in|[cem]m|ex|p[ctx]))',
|
||||||
|
'(?:\\s*\\/\\s*(normal|[\\.\\d]+(?:\\%|in|[cem]m|ex|p[ctx])?))',
|
||||||
|
'?\\s*([-,\\"\\\'\\sa-z]+?)\\s*$'
|
||||||
|
].join(''), 'i');
|
||||||
|
const fontRegExMatchIndex = [
|
||||||
|
'style',
|
||||||
|
'variant',
|
||||||
|
'weight',
|
||||||
|
'size',
|
||||||
|
'lineHeight',
|
||||||
|
'family'
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the list of font families from a font spec. Note that this doesn't work
|
* Get the list of font families from a font spec. Note that this doesn't work
|
||||||
* for font families that have commas in them.
|
* for font families that have commas in them.
|
||||||
* @param {string} fontSpec The CSS font property.
|
* @param {string} fontSpec The CSS font property.
|
||||||
* @param {function(FontParameters):void} callback Called with the font families
|
* @return {FontParameters} The font parameters (or null if the input spec is invalid).
|
||||||
* (or null if the input spec is invalid).
|
|
||||||
*/
|
*/
|
||||||
export const getFontParameters = (function() {
|
export const getFontParameters = function(fontSpec) {
|
||||||
/**
|
const match = fontSpec.match(fontRegEx);
|
||||||
* @type {CSSStyleDeclaration}
|
if (!match) {
|
||||||
*/
|
return null;
|
||||||
let style;
|
}
|
||||||
/**
|
const style = /** @type {FontParameters} */ ({
|
||||||
* @type {Object<string, FontParameters>}
|
lineHeight: 'normal',
|
||||||
*/
|
size: '1.2em',
|
||||||
const cache = {};
|
style: 'normal',
|
||||||
return function(fontSpec, callback) {
|
weight: 'normal',
|
||||||
if (!style) {
|
variant: 'normal'
|
||||||
style = document.createElement('div').style;
|
});
|
||||||
|
for (let i = 0, ii = fontRegExMatchIndex.length; i < ii; ++i) {
|
||||||
|
const value = match[i + 1];
|
||||||
|
if (value !== undefined) {
|
||||||
|
style[fontRegExMatchIndex[i]] = value;
|
||||||
}
|
}
|
||||||
if (!(fontSpec in cache)) {
|
}
|
||||||
style.font = fontSpec;
|
style.families = style.family.split(/,\s?/);
|
||||||
const family = style.fontFamily;
|
return style;
|
||||||
if (!family) {
|
};
|
||||||
callback(null);
|
|
||||||
}
|
|
||||||
const families = family.split(/,\s?/);
|
|
||||||
cache[fontSpec] = {
|
|
||||||
families: families,
|
|
||||||
weight: style.fontWeight,
|
|
||||||
style: style.fontStyle,
|
|
||||||
lineHeight: style.lineHeight
|
|
||||||
};
|
|
||||||
style.font = '';
|
|
||||||
}
|
|
||||||
callback(cache[fontSpec]);
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|||||||
+5
-3
@@ -1,3 +1,5 @@
|
|||||||
|
import {WORKER_OFFSCREEN_CANVAS} from './has.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @module ol/dom
|
* @module ol/dom
|
||||||
*/
|
*/
|
||||||
@@ -14,9 +16,9 @@
|
|||||||
export function createCanvasContext2D(opt_width, opt_height, opt_canvasPool) {
|
export function createCanvasContext2D(opt_width, opt_height, opt_canvasPool) {
|
||||||
const canvas = opt_canvasPool && opt_canvasPool.length ?
|
const canvas = opt_canvasPool && opt_canvasPool.length ?
|
||||||
opt_canvasPool.shift() :
|
opt_canvasPool.shift() :
|
||||||
'document' in self ?
|
WORKER_OFFSCREEN_CANVAS ?
|
||||||
document.createElement('canvas') :
|
new OffscreenCanvas(opt_width || 300, opt_height || 300) :
|
||||||
new OffscreenCanvas(opt_width || 300, opt_height || 300);
|
document.createElement('canvas');
|
||||||
if (opt_width) {
|
if (opt_width) {
|
||||||
canvas.width = opt_width;
|
canvas.width = opt_width;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-16
@@ -37,27 +37,15 @@ export const MAC = ua.indexOf('macintosh') !== -1;
|
|||||||
* @type {number}
|
* @type {number}
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
export const DEVICE_PIXEL_RATIO = (function() {
|
export const DEVICE_PIXEL_RATIO = (typeof self !== 'undefined' ? self.devicePixelRatio : window.devicePixelRatio) || 1;
|
||||||
try {
|
|
||||||
return self.devicePixelRatio;
|
|
||||||
} catch (e) {
|
|
||||||
return window.devicePixelRatio || 1;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The execution context is a window.
|
* The execution context is a worker with OffscreenCanvas available.
|
||||||
* @const
|
* @const
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
export const WINDOW = (function() {
|
export const WORKER_OFFSCREEN_CANVAS = typeof WorkerGlobalScope !== 'undefined' && typeof OffscreenCanvas !== 'undefined' &&
|
||||||
try {
|
self instanceof WorkerGlobalScope; //eslint-disable-line
|
||||||
return 'document' in self;
|
|
||||||
} catch (e) {
|
|
||||||
// ancient browsers don't have `self`
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image.prototype.decode() is supported.
|
* Image.prototype.decode() is supported.
|
||||||
|
|||||||
+27
-45
@@ -6,7 +6,7 @@ import {createCanvasContext2D} from '../dom.js';
|
|||||||
import {clear} from '../obj.js';
|
import {clear} from '../obj.js';
|
||||||
import BaseObject from '../Object.js';
|
import BaseObject from '../Object.js';
|
||||||
import EventTarget from '../events/Target.js';
|
import EventTarget from '../events/Target.js';
|
||||||
import {WINDOW} from '../has.js';
|
import {WORKER_OFFSCREEN_CANVAS} from '../has.js';
|
||||||
import {toString} from '../transform.js';
|
import {toString} from '../transform.js';
|
||||||
|
|
||||||
|
|
||||||
@@ -266,7 +266,8 @@ export const registerFont = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fontCallback(font) {
|
return function(fontSpec) {
|
||||||
|
const font = getFontParameters(fontSpec);
|
||||||
if (!font) {
|
if (!font) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -284,31 +285,6 @@ export const registerFont = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return function(fontSpec) {
|
|
||||||
if (WINDOW) {
|
|
||||||
getFontParameters(fontSpec, fontCallback);
|
|
||||||
} else if (self.postMessage) {
|
|
||||||
/** @type {any} */
|
|
||||||
const worker = self;
|
|
||||||
worker.postMessage({
|
|
||||||
action: 'getFontParameters',
|
|
||||||
font: fontSpec
|
|
||||||
});
|
|
||||||
worker.addEventListener('message', function handler(event) {
|
|
||||||
if (event.data.action === '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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@@ -323,22 +299,29 @@ export const measureTextHeight = (function() {
|
|||||||
*/
|
*/
|
||||||
let div;
|
let div;
|
||||||
const heights = textHeights;
|
const heights = textHeights;
|
||||||
return function(font) {
|
return function(fontSpec) {
|
||||||
let height = heights[font];
|
let height = heights[fontSpec];
|
||||||
if (height == undefined) {
|
if (height == undefined) {
|
||||||
if (!div) {
|
if (WORKER_OFFSCREEN_CANVAS) {
|
||||||
div = document.createElement('div');
|
const font = getFontParameters(fontSpec);
|
||||||
div.innerHTML = 'M';
|
const metrics = measureText(fontSpec, 'Žg');
|
||||||
div.style.margin = '0 !important';
|
const lineHeight = isNaN(Number(font.lineHeight)) ? 1.2 : Number(font.lineHeight);
|
||||||
div.style.padding = '0 !important';
|
textHeights[fontSpec] = lineHeight * (metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent);
|
||||||
div.style.position = 'absolute !important';
|
} else {
|
||||||
div.style.left = '-99999px !important';
|
if (!div) {
|
||||||
|
div = document.createElement('div');
|
||||||
|
div.innerHTML = 'M';
|
||||||
|
div.style.margin = '0 !important';
|
||||||
|
div.style.padding = '0 !important';
|
||||||
|
div.style.position = 'absolute !important';
|
||||||
|
div.style.left = '-99999px !important';
|
||||||
|
}
|
||||||
|
div.style.font = fontSpec;
|
||||||
|
document.body.appendChild(div);
|
||||||
|
height = div.offsetHeight;
|
||||||
|
heights[fontSpec] = height;
|
||||||
|
document.body.removeChild(div);
|
||||||
}
|
}
|
||||||
div.style.font = font;
|
|
||||||
document.body.appendChild(div);
|
|
||||||
height = div.offsetHeight;
|
|
||||||
heights[font] = height;
|
|
||||||
document.body.removeChild(div);
|
|
||||||
}
|
}
|
||||||
return height;
|
return height;
|
||||||
};
|
};
|
||||||
@@ -369,7 +352,6 @@ export function measureTextWidth(font, text) {
|
|||||||
return measureText(font, text).width;
|
return measureText(font, text).width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Measure text width using a cache.
|
* Measure text width using a cache.
|
||||||
* @param {string} font The font.
|
* @param {string} font The font.
|
||||||
@@ -484,13 +466,13 @@ let createTransformStringCanvas = null;
|
|||||||
* @return {string} CSS transform.
|
* @return {string} CSS transform.
|
||||||
*/
|
*/
|
||||||
export function createTransformString(transform) {
|
export function createTransformString(transform) {
|
||||||
if (WINDOW) {
|
if (WORKER_OFFSCREEN_CANVAS) {
|
||||||
|
return toString(transform);
|
||||||
|
} else {
|
||||||
if (!createTransformStringCanvas) {
|
if (!createTransformStringCanvas) {
|
||||||
createTransformStringCanvas = createCanvasContext2D(1, 1).canvas;
|
createTransformStringCanvas = createCanvasContext2D(1, 1).canvas;
|
||||||
}
|
}
|
||||||
createTransformStringCanvas.style.transform = toString(transform);
|
createTransformStringCanvas.style.transform = toString(transform);
|
||||||
return createTransformStringCanvas.style.transform;
|
return createTransformStringCanvas.style.transform;
|
||||||
} else {
|
|
||||||
return toString(transform);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
} from '../../transform.js';
|
} from '../../transform.js';
|
||||||
import {defaultTextAlign, measureTextHeight, measureAndCacheTextWidth, measureTextWidths} from '../canvas.js';
|
import {defaultTextAlign, measureTextHeight, measureAndCacheTextWidth, measureTextWidths} from '../canvas.js';
|
||||||
import RBush from 'rbush/rbush.js';
|
import RBush from 'rbush/rbush.js';
|
||||||
import {WINDOW} from '../../has.js';
|
import {WORKER_OFFSCREEN_CANVAS} from '../../has.js';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,7 +206,7 @@ class Executor {
|
|||||||
contextInstructions.push('lineJoin', strokeState.lineJoin);
|
contextInstructions.push('lineJoin', strokeState.lineJoin);
|
||||||
contextInstructions.push('miterLimit', strokeState.miterLimit);
|
contextInstructions.push('miterLimit', strokeState.miterLimit);
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const Context = WINDOW ? CanvasRenderingContext2D : OffscreenCanvasRenderingContext2D;
|
const Context = WORKER_OFFSCREEN_CANVAS ? OffscreenCanvasRenderingContext2D : CanvasRenderingContext2D;
|
||||||
if (Context.prototype.setLineDash) {
|
if (Context.prototype.setLineDash) {
|
||||||
contextInstructions.push('setLineDash', [strokeState.lineDash]);
|
contextInstructions.push('setLineDash', [strokeState.lineDash]);
|
||||||
contextInstructions.push('lineDashOffset', strokeState.lineDashOffset);
|
contextInstructions.push('lineDashOffset', strokeState.lineDashOffset);
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
/* Basic Options */
|
/* Basic Options */
|
||||||
"target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
|
"target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||||
"lib": ["es2017", "dom"], /* Specify library files to be included in the compilation. */
|
"lib": ["es2017", "dom", "webworker"], /* Specify library files to be included in the compilation. */
|
||||||
"allowJs": true, /* Allow javascript files to be compiled. */
|
"allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
"checkJs": true, /* Report errors in .js files. */
|
"checkJs": true, /* Report errors in .js files. */
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
|
|||||||
Reference in New Issue
Block a user