Files
shields/lib/badge-cli.js
Paul Melnikow cc9a6db853 Speed up font-width computation in most cases (#1390)
Ref: #1379

This takes a naive approach to font-width computation, the most compute-intensive part of rendering badges.

1. Add the widths of the individual characters.
    - These widths are measured on startup using PDFKit.
2. For each character pair, add a kerning adjustment
    - The difference between the width of each character pair, and the sum of the characters' separate widths.
    - These are computed for each character pair on startup using PDFKit.
3. For a string with characters outside the printable ASCII character set, fall back to PDFKit.

This branch averaged 0.041 ms in `makeBadge`, compared to 0.144 ms on master, a speedup of 73%. That was on a test of 10,000 consecutive requests (using the `benchmark-performance.sh` script, now checked in).

The speedup applies to badges containing exclusively printable ASCII characters. It wouldn't be as dramatic on non-ASCII text. Though, we could add some frequently used non-ASCII characters to the cached set.
2017-12-26 23:57:46 -05:00

87 lines
2.3 KiB
JavaScript
Executable File

#!/usr/bin/env node
'use strict';
const { PDFKitTextMeasurer } = require('./text-measurer');
const { makeBadge } = require('./make-badge');
const svg2img = require('./svg-to-img');
const colorscheme = require('./colorscheme.json');
const defaults = require('./defaults');
if (process.argv.length < 4) {
console.log('Usage: badge subject status [:colorscheme] [.output] [@style]');
console.log('Or: badge subject status right-color [left-color] [.output] [@style]');
console.log();
console.log(' colorscheme: one of '
+ Object.keys(colorscheme).join(', ') + '.');
console.log(' left-color, right-color:');
console.log(' #xxx (three hex digits)');
console.log(' #xxxxxx (six hex digits)');
console.log(' color (CSS color)');
console.log(' output:');
console.log(' svg, png, jpg, or gif');
console.log();
console.log('Eg: badge cactus grown :green @flat');
console.log();
process.exit();
}
const fontPath = process.env.FONT_PATH || defaults.font.path;
// Find a format specifier.
let format = 'svg';
let style = '';
for (let i = 4; i < process.argv.length; i++) {
if (process.argv[i][0] === '.') {
format = process.argv[i].slice(1);
process.argv.splice(i, 1);
continue;
}
if (process.argv[i][0] === '@') {
style = process.argv[i].slice(1);
process.argv.splice(i, 1);
continue;
}
}
const subject = process.argv[2];
const status = process.argv[3];
let color = process.argv[4] || ':green';
const colorA = process.argv[5];
const badgeData = {text: [subject, status], format: format};
if (style) {
badgeData.template = style;
}
if (color[0] === ':') {
color = color.slice(1);
if (colorscheme[color] == null) {
// Colorscheme not found.
console.error('Invalid color scheme.');
process.exit(1);
}
badgeData.colorscheme = color;
} else {
badgeData.colorB = color;
if (colorA) { badgeData.colorA = colorA; }
}
// The widths are going to be off if Helvetica-Bold is used, though this
// should print a warning.
const measurer = new PDFKitTextMeasurer(fontPath, 'Helvetica-Bold');
const svg = makeBadge(measurer, badgeData);
if (/png|jpg|gif/.test(format)) {
svg2img(svg, format)
.then(data => {
process.stdout.write(data);
})
.catch(err => {
console.error(err);
process.exit(1);
})
} else {
console.log(svg);
}