tileserver-gl/src/utils.js
2020-07-02 10:28:25 +02:00

131 lines
3.9 KiB
JavaScript

'use strict';
const path = require('path');
const fs = require('fs');
const clone = require('clone');
const glyphCompose = require('@mapbox/glyph-pbf-composite');
module.exports.getPublicUrl = (publicUrl, req) => publicUrl || `${req.protocol}://${req.headers.host}/`;
module.exports.getTileUrls = (req, domains, path, format, publicUrl, aliases) => {
if (domains) {
if (domains.constructor === String && domains.length > 0) {
domains = domains.split(',');
}
const host = req.headers.host;
const hostParts = host.split('.');
const relativeSubdomainsUsable = hostParts.length > 1 &&
!/^([0-9]{1,3}\.){3}[0-9]{1,3}(\:[0-9]+)?$/.test(host);
const newDomains = [];
for (const domain of domains) {
if (domain.indexOf('*') !== -1) {
if (relativeSubdomainsUsable) {
const newParts = hostParts.slice(1);
newParts.unshift(domain.replace('*', hostParts[0]));
newDomains.push(newParts.join('.'));
}
} else {
newDomains.push(domain);
}
}
domains = newDomains;
}
if (!domains || domains.length == 0) {
domains = [req.headers.host];
}
const key = req.query.key;
const queryParams = [];
if (req.query.key) {
queryParams.push(`key=${encodeURIComponent(req.query.key)}`);
}
if (req.query.style) {
queryParams.push(`style=${encodeURIComponent(req.query.style)}`);
}
const query = queryParams.length > 0 ? (`?${queryParams.join('&')}`) : '';
if (aliases && aliases[format]) {
format = aliases[format];
}
const uris = [];
if (!publicUrl) {
for (const domain of domains) {
uris.push(`${req.protocol}://${domain}/${path}/{z}/{x}/{y}.${format}${query}`);
}
} else {
uris.push(`${publicUrl}${path}/{z}/{x}/{y}.${format}${query}`)
}
return uris;
};
module.exports.fixTileJSONCenter = tileJSON => {
if (tileJSON.bounds && !tileJSON.center) {
const fitWidth = 1024;
const tiles = fitWidth / 256;
tileJSON.center = [
(tileJSON.bounds[0] + tileJSON.bounds[2]) / 2,
(tileJSON.bounds[1] + tileJSON.bounds[3]) / 2,
Math.round(
-Math.log((tileJSON.bounds[2] - tileJSON.bounds[0]) / 360 / tiles) /
Math.LN2
)
];
}
};
const getFontPbf = (allowedFonts, fontPath, name, range, fallbacks) => new Promise((resolve, reject) => {
if (!allowedFonts || (allowedFonts[name] && fallbacks)) {
const filename = path.join(fontPath, name, `${range}.pbf`);
if (!fallbacks) {
fallbacks = clone(allowedFonts || {});
}
delete fallbacks[name];
fs.readFile(filename, (err, data) => {
if (err) {
console.error(`ERROR: Font not found: ${name}`);
if (fallbacks && Object.keys(fallbacks).length) {
let fallbackName;
let fontStyle = name.split(' ').pop();
if (['Regular', 'Bold', 'Italic'].indexOf(fontStyle) < 0) {
fontStyle = 'Regular';
}
fallbackName = `Noto Sans ${fontStyle}`;
if (!fallbacks[fallbackName]) {
fallbackName = `Open Sans ${fontStyle}`;
if (!fallbacks[fallbackName]) {
fallbackName = Object.keys(fallbacks)[0];
}
}
console.error(`ERROR: Trying to use ${fallbackName} as a fallback`);
delete fallbacks[fallbackName];
getFontPbf(null, fontPath, fallbackName, range, fallbacks).then(resolve, reject);
} else {
reject(`Font load error: ${name}`);
}
} else {
resolve(data);
}
});
} else {
reject(`Font not allowed: ${name}`);
}
});
module.exports.getFontsPbf = (allowedFonts, fontPath, names, range, fallbacks) => {
const fonts = names.split(',');
const queue = [];
for (const font of fonts) {
queue.push(
getFontPbf(allowedFonts, fontPath, font, range, clone(allowedFonts || fallbacks))
);
}
return Promise.all(queue).then(values => glyphCompose.combine(values));
};