From a0fbf7fb79ed749bff3161cdd9519c6f2549c294 Mon Sep 17 00:00:00 2001 From: Petr Sloup Date: Tue, 26 Jul 2016 18:56:32 +0700 Subject: [PATCH] Fix font compositing (close #32) --- package.json | 1 + src/serve_font.js | 38 ++++---------------------------------- src/serve_rendered.js | 10 +++++++++- src/utils.js | 39 +++++++++++++++++++++++++++++++++++++++ test/style.js | 2 +- 5 files changed, 54 insertions(+), 36 deletions(-) diff --git a/package.json b/package.json index 6eb8b15..881d14e 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "color": "0.11.3", "cors": "2.7.1", "express": "4.14.0", + "glyph-pbf-composite": "0.0.2", "handlebars": "4.0.5", "mapbox-gl-native": "3.2.1", "mbtiles": "0.9.0", diff --git a/src/serve_font.js b/src/serve_font.js index 935703d..1558fb8 100644 --- a/src/serve_font.js +++ b/src/serve_font.js @@ -1,12 +1,9 @@ 'use strict'; -var async = require('async'), - path = require('path'), - fs = require('fs'); - var clone = require('clone'), express = require('express'); +var utils = require('./utils'); module.exports = function(options, allowedFonts) { var app = express().disable('x-powered-by'); @@ -15,41 +12,14 @@ module.exports = function(options, allowedFonts) { var fontPath = options.paths.fonts; - var getFontPbf = function(name, range, callback) { - // if some of the files failed to load (does not exist or not allowed), - // return empty buffer so the other fonts can still work - if (allowedFonts[name]) { - var filename = path.join(fontPath, name, range + '.pbf'); - return fs.readFile(filename, function(err, data) { - if (err) { - console.log('Font load error:', filename); - return callback(null, new Buffer([])); - } else { - return callback(null, data); - } - }); - } else { - return callback(null, new Buffer([])); - } - }; - app.get('/:fontstack/:range([\\d]+-[\\d]+).pbf', function(req, res, next) { var fontstack = decodeURI(req.params.fontstack); var range = req.params.range; - var fonts = fontstack.split(','); - - var queue = []; - fonts.forEach(function(font) { - queue.push(function(callback) { - getFontPbf(font, range, callback); - }); - }); - - return async.parallel(queue, function(err, results) { - var concated = Buffer.concat(results); - if (err || concated.length == 0) { + return utils.getFontsPbf(allowedFonts, fontPath, fontstack, range, + function(err, concated) { + if (err || concated.length === 0) { return res.status(400).send(''); } else { res.header('Content-type', 'application/x-protobuf'); diff --git a/src/serve_rendered.js b/src/serve_rendered.js index cfd2f05..eb62a20 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -56,12 +56,20 @@ module.exports = function(options, repo, params, id) { request: function(req, callback) { var protocol = req.url.split(':')[0]; //console.log('Handling request:', req); - if (protocol == 'sprites' || protocol == 'fonts') { + if (protocol == 'sprites') { var dir = options.paths[protocol]; var file = unescape(req.url).substring(protocol.length + 3); fs.readFile(path.join(dir, file), function(err, data) { callback(err, { data: data }); }); + } else if (protocol == 'fonts') { + var parts = req.url.split('/'); + var fontstack = unescape(parts[2]); + var range = parts[3].split('.')[0]; + utils.getFontsPbf(null, options.paths[protocol], fontstack, range, + function(err, concated) { + callback(err, {data: concated}); + }); } else if (protocol == 'mbtiles') { var parts = req.url.split('/'); var source = map.sources[parts[2]]; diff --git a/src/utils.js b/src/utils.js index fda3b5f..abc084f 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,11 @@ 'use strict'; +var async = require('async'), + path = require('path'), + fs = require('fs'); + +var glyphCompose = require('glyph-pbf-composite'); + module.exports.getTileUrls = function(req, domains, path, format) { if (domains) { @@ -37,3 +43,36 @@ module.exports.fixTileJSONCenter = function(tileJSON) { ]; } }; + +module.exports.getFontsPbf = function(allowedFonts, fontPath, names, range, callback) { + var getFontPbf = function(name, range, callback) { + if (!allowedFonts || allowedFonts[name]) { + var filename = path.join(fontPath, name, range + '.pbf'); + return fs.readFile(filename, function(err, data) { + if (err) { + return callback(new Error('Font load error: ' + name)); + } else { + return callback(null, data); + } + }); + } else { + return callback(new Error('Font not allowed: ' + name)); + } + }; + + var fonts = names.split(','); + var queue = []; + fonts.forEach(function(font) { + queue.push(function(callback) { + getFontPbf(font, range, callback); + }); + }); + + return async.parallel(queue, function(err, results) { + if (err) { + callback(err, new Buffer([])); + } else { + callback(err, glyphCompose.combine(results)); + } + }); +}; diff --git a/test/style.js b/test/style.js index 94990fa..de839c1 100644 --- a/test/style.js +++ b/test/style.js @@ -42,7 +42,7 @@ describe('Fonts', function() { testIs('/fonts/Open Sans Regular/65280-65533.pbf', /application\/x-protobuf/); testIs('/fonts/Open Sans Bold,Open Sans Regular/0-255.pbf', /application\/x-protobuf/); - testIs('/fonts/Nonsense,Open Sans Bold/0-255.pbf', /application\/x-protobuf/); + testIs('/fonts/Nonsense,Open Sans Bold/0-255.pbf', /./, 400); testIs('/fonts/Nonsense/0-255.pbf', /./, 400); testIs('/fonts/Nonsense1,Nonsense2/0-255.pbf', /./, 400);