From b25a6420dda4000d6512929930cf9d2608cd148a Mon Sep 17 00:00:00 2001 From: Martin d'Allens Date: Thu, 23 Nov 2023 18:16:31 +0100 Subject: [PATCH 1/3] chore: simplify alpha premultiplication, now supported by sharp (#1073) Maplibre-native outputs premultiplied pixels values. The sharp library did not support it so we added code to cancel the alpha premultiplication. Note that this can only visible onr raster tiles (and probably static maps). The sharp library now supports premultiplied pixels with the right config. Let's use it: it should be faster and easie to maintain. Feature announced here: https://github.com/lovell/sharp/issues/1599#issuecomment-837004081 Feature developped here by @mnutt: https://github.com/lovell/sharp/pull/2685 Signed-off-by: Martin d'Allens --- src/serve_rendered.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/serve_rendered.js b/src/serve_rendered.js index fbdd1f0..0beb383 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -428,24 +428,9 @@ const respondImage = ( return res.status(500).header('Content-Type', 'text/plain').send(err); } - // Fix semi-transparent outlines on raw, premultiplied input - // https://github.com/maptiler/tileserver-gl/issues/350#issuecomment-477857040 - for (let i = 0; i < data.length; i += 4) { - const alpha = data[i + 3]; - const norm = alpha / 255; - if (alpha === 0) { - data[i] = 0; - data[i + 1] = 0; - data[i + 2] = 0; - } else { - data[i] = data[i] / norm; - data[i + 1] = data[i + 1] / norm; - data[i + 2] = data[i + 2] / norm; - } - } - const image = sharp(data, { raw: { + premultiplied: true, width: params.width * scale, height: params.height * scale, channels: 4, From c9aa26a6de4dfe9fdafa62f1f989b8fdcd66096c Mon Sep 17 00:00:00 2001 From: Martin d'Allens Date: Fri, 24 Nov 2023 17:48:50 +0100 Subject: [PATCH 2/3] fix: listFonts was broken, missing fonts could not fallback (#1076) Promise code never worked: listFonts did not wait for fs.stat() to resolve(). This was not evident because late results were still used. A recent PR made it worse: late results are now ignored. This manifested for styles with missing fonts, no fallback could be used. Signed-off-by: Martin d'Allens --- src/utils.js | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/src/utils.js b/src/utils.js index 3f5cb0d..97ed7ef 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,7 +1,8 @@ 'use strict'; import path from 'path'; -import fs from 'node:fs'; +import fsPromises from 'fs/promises'; +import fs, { existsSync } from 'node:fs'; import clone from 'clone'; import glyphCompose from '@mapbox/glyph-pbf-composite'; @@ -165,30 +166,18 @@ export const getFontsPbf = ( export const listFonts = async (fontPath) => { const existingFonts = {}; - const fontListingPromise = new Promise((resolve, reject) => { - fs.readdir(fontPath, (err, files) => { - if (err) { - reject(err); - return; - } - for (const file of files) { - fs.stat(path.join(fontPath, file), (err, stats) => { - if (err) { - reject(err); - return; - } - if ( - stats.isDirectory() && - fs.existsSync(path.join(fontPath, file, '0-255.pbf')) - ) { - existingFonts[path.basename(file)] = true; - } - }); - } - resolve(); - }); - }); - await fontListingPromise; + + const files = await fsPromises.readdir(fontPath); + for (const file of files) { + const stats = await fsPromises.stat(path.join(fontPath, file)); + if ( + stats.isDirectory() && + existsSync(path.join(fontPath, file, '0-255.pbf')) + ) { + existingFonts[path.basename(file)] = true; + } + } + return existingFonts; }; From 407f6b2e30a1d2b0be265b2c751bf75642ea9f5e Mon Sep 17 00:00:00 2001 From: Martin d'Allens Date: Sun, 26 Nov 2023 02:16:33 +0100 Subject: [PATCH 3/3] Fix crash on ARM during rendering (#1077) * chore: fix crash on ARM during rendering Signed-off-by: Martin d'Allens * chore: remove useless comment Signed-off-by: Martin d'Allens --------- Signed-off-by: Martin d'Allens --- src/serve_rendered.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/serve_rendered.js b/src/serve_rendered.js index 0beb383..da5001e 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -1,12 +1,24 @@ 'use strict'; +// SECTION START +// +// The order of the two imports below is important. +// For an unknown reason, if the order is reversed, rendering can crash. +// This happens on ARM: +// > terminate called after throwing an instance of 'std::runtime_error' +// > what(): Cannot read GLX extensions. +import 'canvas'; +import '@maplibre/maplibre-gl-native'; +// +// SECTION END + import advancedPool from 'advanced-pool'; import fs from 'node:fs'; import path from 'path'; import url from 'url'; import util from 'util'; import zlib from 'zlib'; -import sharp from 'sharp'; // sharp has to be required before node-canvas on linux but after it on windows. see https://github.com/lovell/sharp/issues/371 +import sharp from 'sharp'; import clone from 'clone'; import Color from 'color'; import express from 'express';