Skip to content

Commit

Permalink
Backport #891 to 1.x
Browse files Browse the repository at this point in the history
Parse font using parse-css-font and units-css
  • Loading branch information
LinusU committed Mar 18, 2017
1 parent 3a930e4 commit d316416
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 37 deletions.
67 changes: 31 additions & 36 deletions lib/context2d.js
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,40 +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(',')[0].trim();
// 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[0]
};

return cache[str] = font;
};

Expand Down
4 changes: 3 additions & 1 deletion package.json
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": {
"body-parser": "^1.13.3",
Expand Down
12 changes: 12 additions & 0 deletions test/public/tests.js
Expand Up @@ -988,6 +988,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

0 comments on commit d316416

Please sign in to comment.