Skip to content

Require Pango over "toy" Cairo font methods. Redo the custom font API #715

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 14 commits into from
Oct 23, 2016
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
26 changes: 23 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ node-canvas
$ npm install canvas
```

Unless previously installed you'll _need_ __Cairo__. For system-specific installation view the [Wiki](https://github.com/Automattic/node-canvas/wiki/_pages).
Unless previously installed you'll _need_ __Cairo__ and __Pango__. For system-specific installation view the [Wiki](https://github.com/Automattic/node-canvas/wiki/_pages).

You can quickly install the dependencies by using the command for your OS:

OS | Command
----- | -----
OS X | `brew install pkg-config cairo libpng jpeg giflib`
OS X | `brew install pkg-config cairo pango libpng jpeg giflib`
Ubuntu | `sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++`
Fedora | `sudo yum install cairo cairo-devel cairomm-devel libjpeg-turbo-devel pango pango-devel pangomm pangomm-devel giflib-devel`
Solaris | `pkgin install cairo pkg-config xproto renderproto kbproto xextproto`
Solaris | `pkgin install cairo pango pkg-config xproto renderproto kbproto xextproto`
Windows | [Instructions on our wiki](https://github.com/Automattic/node-canvas/wiki/Installation---Windows)

**El Capitan users:** If you have recently updated to El Capitan and are experiencing trouble when compiling, run the following command: `xcode-select --install`. Read more about the problem [on Stack Overflow](http://stackoverflow.com/a/32929012/148072).
Expand Down Expand Up @@ -182,6 +182,26 @@ canvas.toDataURL('image/jpeg', {opts...}, function(err, jpeg){ }); // see Canvas
canvas.toDataURL('image/jpeg', quality, function(err, jpeg){ }); // spec-following; quality from 0 to 1
```

### Canvas.registerFont for bundled fonts

It can be useful to use a custom font file if you are distributing code that uses node-canvas and a specific font. Or perhaps you are using it to do automated tests and you want the renderings to be the same across operating systems regardless of what fonts are installed.

To do that, you should use `Canvas.registerFont`.

**You need to call it before the Canvas is created**

```javascript
Canvas.registerFont('comicsans.ttf', {family: 'Comic Sans'});

var canvas = new Canvas(500, 500),
ctx = canvas.getContext('2d');

ctx.font = '12px "Comic Sans"';
ctx.fillText(250, 10, 'Everyone hates this font :(');
```

The second argument is an object with properties that resemble the CSS properties that are specified in `@font-face` rules. You must specify at least `family`. `weight`, and `style` are optional (and default to "normal").

### CanvasRenderingContext2D#patternQuality

Given one of the values below will alter pattern (gradients, images, etc) render quality, defaults to _good_.
Expand Down
81 changes: 31 additions & 50 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@
'variables': {
'GTK_Root%': 'C:/GTK', # Set the location of GTK all-in-one bundle
'with_jpeg%': 'false',
'with_gif%': 'false',
'with_pango%': 'false',
'with_freetype%': 'false'
'with_gif%': 'false'
}
}, { # 'OS!="win"'
'variables': {
'with_jpeg%': '<!(./util/has_lib.sh jpeg)',
'with_gif%': '<!(./util/has_lib.sh gif)',
'with_pango%': '<!(./util/has_lib.sh pango)',
'with_freetype%': '<!(./util/has_lib.sh freetype)'
'with_gif%': '<!(./util/has_lib.sh gif)'
}
}]
],
Expand All @@ -26,12 +22,21 @@
'copies': [{
'destination': '<(PRODUCT_DIR)',
'files': [
'<(GTK_Root)/bin/zlib1.dll',
'<(GTK_Root)/bin/libintl-8.dll',
'<(GTK_Root)/bin/libpng14-14.dll',
'<(GTK_Root)/bin/libpangocairo-1.0-0.dll',
'<(GTK_Root)/bin/libpango-1.0-0.dll',
'<(GTK_Root)/bin/libpangoft2-1.0-0.dll',
'<(GTK_Root)/bin/libpangowin32-1.0-0.dll',
'<(GTK_Root)/bin/libcairo-2.dll',
'<(GTK_Root)/bin/libexpat-1.dll',
'<(GTK_Root)/bin/libfontconfig-1.dll',
'<(GTK_Root)/bin/libfreetype-6.dll',
'<(GTK_Root)/bin/libpng14-14.dll',
'<(GTK_Root)/bin/zlib1.dll',
'<(GTK_Root)/bin/libglib-2.0-0.dll',
'<(GTK_Root)/bin/libgobject-2.0-0.dll',
'<(GTK_Root)/bin/libgmodule-2.0-0.dll',
'<(GTK_Root)/bin/libgthread-2.0-0.dll',
'<(GTK_Root)/bin/libexpat-1.dll'
]
}]
}]
Expand All @@ -48,17 +53,27 @@
'src/color.cc',
'src/Image.cc',
'src/ImageData.cc',
'src/register_font.cc',
'src/init.cc'
],
'conditions': [
['OS=="win"', {
'libraries': [
'-l<(GTK_Root)/lib/cairo.lib',
'-l<(GTK_Root)/lib/libpng.lib'
'-l<(GTK_Root)/lib/libpng.lib',
'-l<(GTK_Root)/lib/pangocairo-1.0.lib',
'-l<(GTK_Root)/lib/pango-1.0.lib',
'-l<(GTK_Root)/lib/freetype.lib',
'-l<(GTK_Root)/lib/glib-2.0.lib',
'-l<(GTK_Root)/lib/gobject-2.0.lib'
],
'include_dirs': [
'<(GTK_Root)/include',
'<(GTK_Root)/include/cairo',
'<(GTK_Root)/include/pango-1.0',
'<(GTK_Root)/include/glib-2.0',
'<(GTK_Root)/include/freetype2',
'<(GTK_Root)/lib/glib-2.0/include'
],
'defines': [
'_USE_MATH_DEFINES' # for M_PI
Expand Down Expand Up @@ -87,49 +102,15 @@
'libraries': [
'<!@(pkg-config pixman-1 --libs)',
'<!@(pkg-config cairo --libs)',
'<!@(pkg-config libpng --libs)'
'<!@(pkg-config libpng --libs)',
'<!@(pkg-config pangocairo --libs)',
'<!@(pkg-config freetype2 --libs)'
],
'include_dirs': [
'<!@(pkg-config cairo --cflags-only-I | sed s/-I//g)',
'<!@(pkg-config libpng --cflags-only-I | sed s/-I//g)'
]
}],
['with_freetype=="true"', {
'defines': [
'HAVE_FREETYPE'
],
'sources': [
'src/FontFace.cc'
],
'conditions': [
['OS=="win"', {
# No support for windows right now.
}, { # 'OS!="win"'
'include_dirs': [ # tried to pass through cflags but failed.
# Need to include the header files of cairo AND freetype.
# Looking up the includes of cairo does both.
'<!@(pkg-config cairo --cflags-only-I | sed s/-I//g)'
]
}]
]
}],
['with_pango=="true"', {
'defines': [
'HAVE_PANGO'
],
'conditions': [
['OS=="win"', {
'libraries': [
'-l<(GTK_Root)/lib/pangocairo.lib'
]
}, { # 'OS!="win"'
'include_dirs': [ # tried to pass through cflags but failed
'<!@(pkg-config pangocairo --cflags-only-I | sed s/-I//g)'
],
'libraries': [
'<!@(pkg-config pangocairo --libs)'
]
}]
'<!@(pkg-config libpng --cflags-only-I | sed s/-I//g)',
'<!@(pkg-config pangocairo --cflags-only-I | sed s/-I//g)',
'<!@(pkg-config freetype2 --cflags-only-I | sed s/-I//g)'
]
}],
['with_jpeg=="true"', {
Expand Down
21 changes: 8 additions & 13 deletions examples/font.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,22 @@ var fs = require('fs')
var path = require('path')
var Canvas = require('..')

var Font = Canvas.Font

if (!Font) {
throw new Error('Need to compile with font support')
}

function fontFile (name) {
return path.join(__dirname, '/pfennigFont/', name)
}

var pfennigFont = new Font('pfennigFont', fontFile('Pfennig.ttf'))
pfennigFont.addFace(fontFile('PfennigBold.ttf'), 'bold')
pfennigFont.addFace(fontFile('PfennigItalic.ttf'), 'normal', 'italic')
pfennigFont.addFace(fontFile('PfennigBoldItalic.ttf'), 'bold', 'italic')
// Pass each font, including all of its individual variants if there are any, to
// `registerFont`. When you set `ctx.font`, refer to the styles and the family
// name as it is embedded in the TTF. If you aren't sure, open the font in
// FontForge and visit Element -> Font Information and copy the Family Name
Canvas.registerFont(fontFile('Pfennig.ttf'), {family: 'pfennigFont'})
Canvas.registerFont(fontFile('PfennigBold.ttf'), {family: 'pfennigFont', weight: 'bold'})
Canvas.registerFont(fontFile('PfennigItalic.ttf'), {family: 'pfennigFont', style: 'italic'})
Canvas.registerFont(fontFile('PfennigBoldItalic.ttf'), {family: 'pfennigFont', weight: 'bold', style: 'italic'})

var canvas = new Canvas(320, 320)
var ctx = canvas.getContext('2d')

// Tell the ctx to use the font.
ctx.addFont(pfennigFont)

ctx.font = 'normal normal 50px Helvetica'

ctx.fillText('Quo Vaids?', 0, 70)
Expand Down
28 changes: 6 additions & 22 deletions lib/canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ var canvas = require('./bindings')
, PNGStream = require('./pngstream')
, PDFStream = require('./pdfstream')
, JPEGStream = require('./jpegstream')
, FontFace = canvas.FontFace
, fs = require('fs')
, packageJson = require("../package.json")
, FORMATS = ['image/png', 'image/jpeg'];
Expand Down Expand Up @@ -76,28 +75,13 @@ exports.JPEGStream = JPEGStream;
exports.Image = Image;
exports.ImageData = canvas.ImageData;

if (FontFace) {
var Font = function Font(name, path, idx) {
this.name = name;
this._faces = {};

this.addFace(path, 'normal', 'normal', idx);
};

Font.prototype.addFace = function(path, weight, style, idx) {
style = style || 'normal';
weight = weight || 'normal';

var face = new FontFace(path, idx || 0);
this._faces[weight + '-' + style] = face;
};

Font.prototype.getFace = function(weightStyle) {
return this._faces[weightStyle] || this._faces['normal-normal'];
};
/**
* Resolve paths for registerFont
*/

exports.Font = Font;
}
Canvas.registerFont = function(src, fontFace){
return Canvas._registerFont(fs.realpathSync(src), fontFace);
};

/**
* Context2d implementation.
Expand Down
39 changes: 9 additions & 30 deletions lib/context2d.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ var parseFont = exports.parseFont = function(str){
font.style = captures[2] || 'normal';
font.size = parseFloat(captures[3]);
font.unit = captures[4];
font.family = captures[5].replace(/["']/g, '').split(',')[0].trim();
font.family = captures[5].replace(/["']/g, '').split(',').map(function (family) {
return family.trim();
}).join(',');

// TODO: dpi
// TODO: remaining unit conversion
Expand Down Expand Up @@ -235,19 +237,6 @@ Context2d.prototype.__defineGetter__('strokeStyle', function(){
return this.lastStrokeStyle || this.strokeColor;
});

/**
* Register `font` for usage.
*
* @param {Font} font
* @api public
*/

Context2d.prototype.addFont = function(font) {
this._fonts = this._fonts || {};
if (this._fonts[font.name]) return;
this._fonts[font.name] = font;
};

/**
* Set font.
*
Expand All @@ -261,22 +250,12 @@ Context2d.prototype.__defineSetter__('font', function(val){
var font;
if (font = parseFont(val)) {
this.lastFontString = val;

var fonts = this._fonts;
if (fonts && fonts[font.family]) {
var fontObj = fonts[font.family];
var type = font.weight + '-' + font.style;

var fontFace = fontObj.getFace(type);
this._setFontFace(fontFace, font.size);
} else {
this._setFont(
font.weight
, font.style
, font.size
, font.unit
, font.family);
}
this._setFont(
font.weight
, font.style
, font.size
, font.unit
, font.family);
}
}
});
Expand Down
Loading