Skip to content

Commit d316416

Browse files
committed
Backport Automattic#891 to 1.x
Parse font using parse-css-font and units-css
1 parent 3a930e4 commit d316416

File tree

3 files changed

+46
-37
lines changed

3 files changed

+46
-37
lines changed

lib/context2d.js

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ var canvas = require('./bindings')
1616
, CanvasPattern = canvas.CanvasPattern
1717
, ImageData = canvas.ImageData;
1818

19+
var parseCssFont = require('parse-css-font');
20+
21+
var unitsCss = require('units-css');
22+
1923
/**
2024
* Export `Context2d` as the module.
2125
*/
@@ -34,26 +38,6 @@ var cache = {};
3438

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

37-
/**
38-
* Font RegExp helpers.
39-
*/
40-
41-
var weights = 'normal|bold|bolder|lighter|[1-9]00'
42-
, styles = 'normal|italic|oblique'
43-
, units = 'px|pt|pc|in|cm|mm|%'
44-
, string = '\'([^\']+)\'|"([^"]+)"|[\\w-]+';
45-
46-
/**
47-
* Font parser RegExp;
48-
*/
49-
50-
var fontre = new RegExp('^ *'
51-
+ '(?:(' + weights + ') *)?'
52-
+ '(?:(' + styles + ') *)?'
53-
+ '([\\d\\.]+)(' + units + ') *'
54-
+ '((?:' + string + ')( *, *(?:' + string + '))*)'
55-
);
56-
5741
/**
5842
* Parse font `str`.
5943
*
@@ -62,40 +46,51 @@ var fontre = new RegExp('^ *'
6246
* @api private
6347
*/
6448

65-
var parseFont = exports.parseFont = function(str){
66-
var font = {}
67-
, captures = fontre.exec(str);
49+
var parseFont = exports.parseFont = function(str) {
50+
var parsedFont;
6851

69-
// Invalid
70-
if (!captures) return;
52+
// Try to parse the font string using parse-css-font.
53+
// It will throw an exception if it fails.
54+
try {
55+
parsedFont = parseCssFont(str);
56+
}
57+
catch (e) {
58+
// Invalid
59+
return;
60+
}
7161

7262
// Cached
7363
if (cache[str]) return cache[str];
7464

75-
// Populate font object
76-
font.weight = captures[1] || 'normal';
77-
font.style = captures[2] || 'normal';
78-
font.size = parseFloat(captures[3]);
79-
font.unit = captures[4];
80-
font.family = captures[5].replace(/["']/g, '').split(',')[0].trim();
65+
// Parse size into value and unit using units-css
66+
var size = unitsCss.parse(parsedFont.size);
8167

8268
// TODO: dpi
8369
// TODO: remaining unit conversion
84-
switch (font.unit) {
70+
switch (size.unit) {
8571
case 'pt':
86-
font.size /= .75;
72+
size.value /= .75;
8773
break;
8874
case 'in':
89-
font.size *= 96;
75+
size.value *= 96;
9076
break;
9177
case 'mm':
92-
font.size *= 96.0 / 25.4;
78+
size.value *= 96.0 / 25.4;
9379
break;
9480
case 'cm':
95-
font.size *= 96.0 / 2.54;
81+
size.value *= 96.0 / 2.54;
9682
break;
9783
}
9884

85+
// Populate font object
86+
var font = {
87+
weight: parsedFont.weight,
88+
style: parsedFont.style,
89+
size: size.value,
90+
unit: size.unit,
91+
family: parsedFont.family[0]
92+
};
93+
9994
return cache[str] = font;
10095
};
10196

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
"test-server": "node test/server.js"
3030
},
3131
"dependencies": {
32-
"nan": "^2.4.0"
32+
"nan": "^2.4.0",
33+
"parse-css-font": "^2.0.2",
34+
"units-css": "^0.4.0"
3335
},
3436
"devDependencies": {
3537
"body-parser": "^1.13.3",

test/public/tests.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,18 @@ tests['font family invalid'] = function(ctx){
988988
ctx.fillText("14px Invalid, Impact", 100, 100);
989989
};
990990

991+
tests['font style variant weight size family'] = function (ctx) {
992+
ctx.strokeStyle = '#666'
993+
ctx.strokeRect(0, 0, 200, 200)
994+
ctx.lineTo(0, 100)
995+
ctx.lineTo(200, 100)
996+
ctx.stroke()
997+
998+
ctx.font = 'normal normal normal 16px Impact'
999+
ctx.textAlign = 'center'
1000+
ctx.fillText('normal normal normal 16px', 100, 100)
1001+
}
1002+
9911003
tests['globalCompositeOperation source-over'] = function(ctx){
9921004
ctx.fillStyle = 'blue';
9931005
ctx.fillRect(0,0,100,100);

0 commit comments

Comments
 (0)