Skip to content

Parse font using parse-css-font and units-css #891

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 31 additions & 38 deletions lib/context2d.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ var canvas = require('./bindings')
, CanvasPattern = canvas.CanvasPattern
, ImageData = canvas.ImageData;

var parseCssFont = require('parse-css-font');

var unitsCss = require('units-css');

/**
* Export `Context2d` as the module.
*/
Expand All @@ -34,26 +38,6 @@ var cache = {};

var baselines = ['alphabetic', 'top', 'bottom', 'middle', 'ideographic', 'hanging'];

/**
* Font RegExp helpers.
*/

var weights = 'normal|bold|bolder|lighter|[1-9]00'
, styles = 'normal|italic|oblique'
, units = 'px|pt|pc|in|cm|mm|%'
, string = '\'([^\']+)\'|"([^"]+)"|[\\w-]+';

/**
* Font parser RegExp;
*/

var fontre = new RegExp('^ *'
+ '(?:(' + weights + ') *)?'
+ '(?:(' + styles + ') *)?'
+ '([\\d\\.]+)(' + units + ') *'
+ '((?:' + string + ')( *, *(?:' + string + '))*)'
);

/**
* Parse font `str`.
*
Expand All @@ -62,42 +46,51 @@ var fontre = new RegExp('^ *'
* @api private
*/

var parseFont = exports.parseFont = function(str){
var font = {}
, captures = fontre.exec(str);
var parseFont = exports.parseFont = function(str) {
var parsedFont;

// Invalid
if (!captures) return;
// Try to parse the font string using parse-css-font.
// It will throw an exception if it fails.
try {
parsedFont = parseCssFont(str);
}
catch (e) {
// Invalid
return;
}

// Cached
if (cache[str]) return cache[str];

// Populate font object
font.weight = captures[1] || 'normal';
font.style = captures[2] || 'normal';
font.size = parseFloat(captures[3]);
font.unit = captures[4];
font.family = captures[5].replace(/["']/g, '').split(',').map(function (family) {
return family.trim();
}).join(',');
// Parse size into value and unit using units-css
var size = unitsCss.parse(parsedFont.size);

// TODO: dpi
// TODO: remaining unit conversion
switch (font.unit) {
switch (size.unit) {
case 'pt':
font.size /= .75;
size.value /= .75;
break;
case 'in':
font.size *= 96;
size.value *= 96;
break;
case 'mm':
font.size *= 96.0 / 25.4;
size.value *= 96.0 / 25.4;
break;
case 'cm':
font.size *= 96.0 / 2.54;
size.value *= 96.0 / 2.54;
break;
}

// Populate font object
var font = {
weight: parsedFont.weight,
style: parsedFont.style,
size: size.value,
unit: size.unit,
family: parsedFont.family.join(',')
};

return cache[str] = font;
};

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
"test-server": "node test/server.js"
},
"dependencies": {
"nan": "^2.4.0"
"nan": "^2.4.0",
"parse-css-font": "^2.0.2",
"units-css": "^0.4.0"
},
"devDependencies": {
"express": "^4.14.0",
Expand Down
12 changes: 12 additions & 0 deletions test/public/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,18 @@ tests['font family invalid'] = function (ctx) {
ctx.fillText('14px Invalid, Impact', 100, 100)
}

tests['font style variant weight size family'] = function (ctx) {
ctx.strokeStyle = '#666'
ctx.strokeRect(0, 0, 200, 200)
ctx.lineTo(0, 100)
ctx.lineTo(200, 100)
ctx.stroke()

ctx.font = 'normal normal normal 16px Impact'
ctx.textAlign = 'center'
ctx.fillText('normal normal normal 16px', 100, 100)
}

tests['globalCompositeOperation source-over'] = function (ctx) {
ctx.fillStyle = 'blue'
ctx.fillRect(0, 0, 100, 100)
Expand Down