Skip to content

Commit f002e1a

Browse files
committed
Render different font variants with pango - WIP
1 parent 3d54505 commit f002e1a

File tree

6 files changed

+73
-28
lines changed

6 files changed

+73
-28
lines changed

lib/context2d.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ var parseFont = exports.parseFont = function(str) {
8686
var font = {
8787
weight: parsedFont.weight,
8888
style: parsedFont.style,
89+
variant: parsedFont.variant,
8990
size: size.value,
9091
unit: size.unit,
9192
family: parsedFont.family.join(',')
@@ -246,6 +247,7 @@ Context2d.prototype.__defineSetter__('font', function(val){
246247
this._setFont(
247248
font.weight
248249
, font.style
250+
, font.variant
249251
, font.size
250252
, font.unit
251253
, font.family);

src/Canvas.cc

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,14 +605,17 @@ NAN_METHOD(Canvas::RegisterFont) {
605605
Local<String> family_prop = Nan::New<String>("family").ToLocalChecked();
606606
Local<String> weight_prop = Nan::New<String>("weight").ToLocalChecked();
607607
Local<String> style_prop = Nan::New<String>("style").ToLocalChecked();
608+
Local<String> variant_props = Nan::New<String>("variant").ToLocalChecked();
608609

609610
char *family = str_value(js_user_desc->Get(family_prop), NULL, false);
610611
char *weight = str_value(js_user_desc->Get(weight_prop), "normal", true);
611612
char *style = str_value(js_user_desc->Get(style_prop), "normal", false);
613+
char *variant = str_value(js_user_desc->Get(variant_props), "normal", true);
612614

613-
if (family && weight && style) {
615+
if (family && weight && style && variant) {
614616
pango_font_description_set_weight(user_desc, Canvas::GetWeightFromCSSString(weight));
615617
pango_font_description_set_style(user_desc, Canvas::GetStyleFromCSSString(style));
618+
pango_font_description_set_variant(user_desc, Canvas::GetVariantFromCSSString(variant));
616619
pango_font_description_set_family(user_desc, family);
617620

618621
std::vector<FontFace>::iterator it = _font_face_list.begin();
@@ -644,6 +647,7 @@ NAN_METHOD(Canvas::RegisterFont) {
644647
g_free(family);
645648
g_free(weight);
646649
g_free(style);
650+
g_free(variant);
647651
}
648652

649653
/*
@@ -759,6 +763,28 @@ Canvas::GetWeightFromCSSString(const char *weight) {
759763
return w;
760764
}
761765

766+
/*
767+
* Get a PangoVariant from a CSS string ("normal", "small-caps", etc)
768+
* Only "normal" and "small-caps" are supported.
769+
*/
770+
771+
PangoVariant
772+
Canvas::GetVariantFromCSSString(const char *variant) {
773+
PangoVariant v = PANGO_VARIANT_NORMAL;
774+
775+
if (strlen(variant) > 0) {
776+
if (0 == strcmp("small-caps", variant) ||
777+
0 == strcmp("all-small-caps", variant) ||
778+
0 == strcmp("petite-caps", variant) ||
779+
0 == strcmp("all-petite-caps", variant) ||
780+
0 == strcmp("unicase", variant)) {
781+
v = PANGO_VARIANT_SMALL_CAPS;
782+
}
783+
}
784+
785+
return v;
786+
}
787+
762788
/*
763789
* Given a user description, return a description that will select the
764790
* font either from the system or @font-face

src/Canvas.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class Canvas: public Nan::ObjectWrap {
8888
static int EIO_AfterToBuffer(eio_req *req);
8989
#endif
9090
static PangoWeight GetWeightFromCSSString(const char *weight);
91+
static PangoVariant GetVariantFromCSSString(const char *variant);
9192
static PangoStyle GetStyleFromCSSString(const char *style);
9293
static PangoFontDescription *ResolveFontDescription(const PangoFontDescription *desc);
9394

src/CanvasRenderingContext2d.cc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,7 @@ NAN_METHOD(Context2d::MoveTo) {
17951795
* Set font:
17961796
* - weight
17971797
* - style
1798+
* - variant
17981799
* - size
17991800
* - unit
18001801
* - family
@@ -1804,15 +1805,17 @@ NAN_METHOD(Context2d::SetFont) {
18041805
// Ignore invalid args
18051806
if (!info[0]->IsString()
18061807
|| !info[1]->IsString()
1807-
|| !info[2]->IsNumber()
1808-
|| !info[3]->IsString()
1809-
|| !info[4]->IsString()) return;
1808+
|| !info[2]->IsString()
1809+
|| !info[3]->IsNumber()
1810+
|| !info[4]->IsString()
1811+
|| !info[5]->IsString()) return;
18101812

18111813
String::Utf8Value weight(info[0]);
18121814
String::Utf8Value style(info[1]);
1813-
double size = info[2]->NumberValue();
1814-
String::Utf8Value unit(info[3]);
1815-
String::Utf8Value family(info[4]);
1815+
String::Utf8Value variant(info[2]);
1816+
double size = info[3]->NumberValue();
1817+
String::Utf8Value unit(info[4]);
1818+
String::Utf8Value family(info[5]);
18161819

18171820
Context2d *context = Nan::ObjectWrap::Unwrap<Context2d>(info.This());
18181821

@@ -1821,6 +1824,7 @@ NAN_METHOD(Context2d::SetFont) {
18211824

18221825
pango_font_description_set_style(desc, Canvas::GetStyleFromCSSString(*style));
18231826
pango_font_description_set_weight(desc, Canvas::GetWeightFromCSSString(*weight));
1827+
pango_font_description_set_variant(desc, Canvas::GetVariantFromCSSString(*variant));
18241828

18251829
if (strlen(*family) > 0) pango_font_description_set_family(desc, *family);
18261830

test/canvas.test.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,47 +28,47 @@ describe('Canvas', function () {
2828
it('.parseFont()', function () {
2929
var tests = [
3030
'20px Arial'
31-
, { size: 20, unit: 'px', family: 'Arial' }
31+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 20, unit: 'px', family: 'Arial' }
3232
, '20pt Arial'
33-
, { size: 26.666666666666668, unit: 'pt', family: 'Arial' }
33+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 26.666666666666668, unit: 'pt', family: 'Arial' }
3434
, '20.5pt Arial'
35-
, { size: 27.333333333333332, unit: 'pt', family: 'Arial' }
35+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 27.333333333333332, unit: 'pt', family: 'Arial' }
3636
, '20% Arial'
37-
, { size: 20, unit: '%', family: 'Arial' }
37+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 20, unit: '%', family: 'Arial' }
3838
, '20mm Arial'
39-
, { size: 75.59055118110237, unit: 'mm', family: 'Arial' }
39+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 75.59055118110237, unit: 'mm', family: 'Arial' }
4040
, '20px serif'
41-
, { size: 20, unit: 'px', family: 'serif' }
41+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 20, unit: 'px', family: 'serif' }
4242
, '20px sans-serif'
43-
, { size: 20, unit: 'px', family: 'sans-serif' }
43+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 20, unit: 'px', family: 'sans-serif' }
4444
, '20px monospace'
45-
, { size: 20, unit: 'px', family: 'monospace' }
45+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 20, unit: 'px', family: 'monospace' }
4646
, '50px Arial, sans-serif'
47-
, { size: 50, unit: 'px', family: 'Arial,sans-serif' }
47+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 50, unit: 'px', family: 'Arial,sans-serif' }
4848
, 'bold italic 50px Arial, sans-serif'
49-
, { style: 'italic', weight: 'bold', size: 50, unit: 'px', family: 'Arial,sans-serif' }
49+
, { style: 'italic', variant: 'normal', weight: 'bold', size: 50, unit: 'px', family: 'Arial,sans-serif' }
5050
, '50px Helvetica , Arial, sans-serif'
51-
, { size: 50, unit: 'px', family: 'Helvetica,Arial,sans-serif' }
51+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 50, unit: 'px', family: 'Helvetica,Arial,sans-serif' }
5252
, '50px "Helvetica Neue", sans-serif'
53-
, { size: 50, unit: 'px', family: 'Helvetica Neue,sans-serif' }
53+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 50, unit: 'px', family: 'Helvetica Neue,sans-serif' }
5454
, '50px "Helvetica Neue", "foo bar baz" , sans-serif'
55-
, { size: 50, unit: 'px', family: 'Helvetica Neue,foo bar baz,sans-serif' }
55+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 50, unit: 'px', family: 'Helvetica Neue,foo bar baz,sans-serif' }
5656
, "50px 'Helvetica Neue'"
57-
, { size: 50, unit: 'px', family: 'Helvetica Neue' }
57+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 50, unit: 'px', family: 'Helvetica Neue' }
5858
, 'italic 20px Arial'
59-
, { size: 20, unit: 'px', style: 'italic', family: 'Arial' }
59+
, { style: 'italic', variant: 'normal', weight: 'normal', size: 20, unit: 'px', family: 'Arial' }
6060
, 'oblique 20px Arial'
61-
, { size: 20, unit: 'px', style: 'oblique', family: 'Arial' }
61+
, { style: 'oblique', variant: 'normal', weight: 'normal', size: 20, unit: 'px', family: 'Arial' }
6262
, 'normal 20px Arial'
63-
, { size: 20, unit: 'px', style: 'normal', family: 'Arial' }
63+
, { style: 'normal', variant: 'normal', weight: 'normal', size: 20, unit: 'px', family: 'Arial' }
6464
, '300 20px Arial'
65-
, { size: 20, unit: 'px', weight: '300', family: 'Arial' }
65+
, { style: 'normal', variant: 'normal', weight: '300', size: 20, unit: 'px', family: 'Arial' }
6666
, '800 20px Arial'
67-
, { size: 20, unit: 'px', weight: '800', family: 'Arial' }
67+
, { style: 'normal', variant: 'normal', weight: '800', size: 20, unit: 'px', family: 'Arial' }
6868
, 'bolder 20px Arial'
69-
, { size: 20, unit: 'px', weight: 'bolder', family: 'Arial' }
69+
, { style: 'normal', variant: 'normal', weight: 'bolder', size: 20, unit: 'px', family: 'Arial' }
7070
, 'lighter 20px Arial'
71-
, { size: 20, unit: 'px', weight: 'lighter', family: 'Arial' }
71+
, { style: 'normal', variant: 'normal', weight: 'lighter', size: 20, unit: 'px', family: 'Arial' }
7272
];
7373

7474
for (var i = 0, len = tests.length; i < len; ++i) {

test/public/tests.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,18 @@ tests['font style variant weight size family'] = function (ctx) {
10111011
ctx.fillText('normal normal normal 16px', 100, 100)
10121012
}
10131013

1014+
tests['small-caps'] = function (ctx) {
1015+
ctx.strokeStyle = '#666'
1016+
ctx.strokeRect(0, 0, 200, 200)
1017+
ctx.lineTo(0, 100)
1018+
ctx.lineTo(200, 100)
1019+
ctx.stroke()
1020+
1021+
ctx.font = 'small-caps 16px sans-serif'
1022+
ctx.textAlign = 'center'
1023+
ctx.fillText('small-caps', 100, 100)
1024+
}
1025+
10141026
tests['globalCompositeOperation source-over'] = function (ctx) {
10151027
ctx.fillStyle = 'blue'
10161028
ctx.fillRect(0, 0, 100, 100)

0 commit comments

Comments
 (0)