opentype.js
Advanced tools
Comparing version 0.6.3 to 0.6.4
{ | ||
"name": "opentype.js", | ||
"version": "0.6.3", | ||
"version": "0.6.4", | ||
"main": "dist/opentype.js", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -9,7 +9,9 @@ // This example shows how to create a font from scratch using node.js. | ||
var UNITS_PER_EM = 1000; | ||
var ASCENDER = 800; | ||
var DESCENDER = -200; | ||
var ASCENDER = 900; | ||
var DESCENDER = -100; | ||
var SCALE = 80; | ||
// The glyphs are defined as simple, single-contour paths. | ||
// This is the minimally required set for OS X Font Book to accept it as a "Latin" font | ||
// and show it in the font selection menu. | ||
var GLYPH_MAP = { | ||
@@ -42,7 +44,44 @@ A: [[0, 0], [4, 10], [8, 0]], | ||
Z: [[0, 10], [7, 10], [7, 7], [3, 3], [7, 3], [7, 0], [0, 0], [0, 3], [4, 7], [0, 7]], | ||
_: [[0, 0], [0, 1], [8, 1], [8, 0]] | ||
a: [[0, 0], [4, 10], [8, 0]], | ||
b: [[0, 0], [0, 10], [5, 10], [5, 5], [7, 5], [7, 0]], | ||
c: [[0, 0], [0, 10], [8, 10], [8, 6], [3, 6], [3, 4], [8, 4], [8, 0]], | ||
d: [[0, 0], [0, 3], [2, 3], [2, 7], [0, 7], [0, 10], [8, 10], [8, 0]], | ||
e: [[0, 0], [0, 10], [8, 10], [8, 7], [3, 7], [3, 6], [5, 6], [5, 4], [3, 4], [3, 3], [8, 3], [8, 0]], | ||
f: [[0, 0], [0, 3], [0, 10], [8, 10], [8, 7], [3, 7], [3, 6], [5, 6], [5, 3], [3, 3], [3, 0]], | ||
g: [[0, 0], [0, 3], [0, 10], [8, 10], [8, 7], [3, 7], [3, 3], [5, 3], [5, 5], [8, 5], [8, 0]], | ||
h: [[0, 0], [0, 3], [0, 7], [0, 10], [3, 10], [3, 7], [5, 7], [5, 10], [8, 10], [8, 0], [5, 0], [5, 3], [3, 3], [3, 0]], | ||
i: [[0, 0], [0, 10], [3, 10], [3, 0]], | ||
j: [[0, 0], [0, 3], [4, 3], [4, 10], [7, 10], [7, 0]], | ||
k: [[0, 0], [0, 10], [3, 10], [3, 7], [5, 10], [8, 10], [5, 5], [8, 0], [5, 0], [3, 3], [3, 0]], | ||
l: [[0, 0], [0, 10], [3, 10], [3, 3], [7, 3], [7, 0]], | ||
m: [[0, 0], [0, 10], [3, 10], [4, 8], [5, 10], [8, 10], [8, 0], [5, 0], [5, 4], [4, 3], [3, 4], [3, 0]], | ||
n: [[0, 0], [0, 10], [3, 10], [3, 9], [5, 7], [5, 10], [8, 10], [8, 0], [5, 0], [5, 3], [3, 5], [3, 0]], | ||
o: [[0, 0], [0, 10], [7, 10], [7, 0]], | ||
p: [[0, 0], [0, 10], [7, 10], [7, 4], [3, 4], [3, 0]], | ||
q: [[0, 0], [0, 10], [7, 10], [7, 0], [6, 0], [7, -1], [4, -1], [3, 0]], | ||
r: [[0, 0], [0, 10], [7, 10], [7, 4], [5, 4], [7, 0], [4, 0], [3, 2], [3, 0]], | ||
s: [[7, 10], [7, 7], [3, 7], [3, 6], [7, 6], [7, 0], [0, 0], [0, 3], [4, 3], [4, 4], [0, 4], [0, 10]], | ||
t: [[2, 0], [2, 7], [0, 7], [0, 10], [7, 10], [7, 7], [5, 7], [5, 0]], | ||
u: [[0, 0], [0, 10], [3, 10], [3, 3], [5, 3], [5, 10], [8, 10], [8, 0]], | ||
v: [[0, 10], [3, 10], [4, 6], [5, 10], [8, 10], [5, 0], [3, 0]], | ||
w: [[0, 10], [3, 10], [4, 6], [5, 8], [6, 6], [7, 10], [10, 10], [8, 0], [6, 0], [5, 3], [4, 0], [2, 0]], | ||
x: [[0, 10], [3, 10], [4, 8], [5, 10], [8, 10], [5, 5], [8, 0], [5, 0], [4, 2], [3, 0], [0, 0], [3, 5]], | ||
y: [[0, 10], [3, 10], [4, 8], [5, 10], [8, 10], [5, 5], [5, 0], [3, 0], [3, 5]], | ||
z: [[0, 10], [7, 10], [7, 7], [3, 3], [7, 3], [7, 0], [0, 0], [0, 3], [4, 7], [0, 7]], | ||
0: [[0, 0], [0, 10], [7, 10], [7, 0]], | ||
1: [[0, 8], [3, 10], [6, 10], [6, 0], [3, 0], [3, 7], [0, 5]], | ||
2: [[0, 6], [0, 10], [9, 10], [9, 7], [4, 3], [9, 3], [9, 0], [0, 0], [0, 3], [5, 7], [3, 7], [3, 6]], | ||
3: [[0, 10], [8, 10], [8, 0], [0, 0], [0, 3], [5, 3], [5, 4], [3, 4], [3, 6], [5, 6], [5, 7], [5, 7], [0, 7]], | ||
4: [[0, 6], [3, 10], [6, 10], [6, 6], [8, 6], [8, 3], [6, 3], [6, 0], [3, 0], [3, 3], [0, 3]], | ||
5: [[0, 3], [0, 0], [8, 0], [8, 6], [3, 6], [3, 7], [8, 7], [8, 10], [0, 10], [0, 4], [5, 4], [5, 2], [2, 2], [2, 3]], | ||
6: [[8, 7], [3, 7], [3, 5], [4, 6], [8, 6], [8, 0], [0, 0], [0, 3], [0, 8], [0, 10], [5, 10], [8, 10]], | ||
7: [[0, 10], [8, 10], [5, 0], [2, 0], [4, 7], [0, 7]], | ||
8: [[0, 0], [0, 3], [2, 5], [0, 7], [0, 10], [8, 10], [8, 7], [6, 5], [8, 3], [8, 0]], | ||
9: [[0, 3], [5, 3], [5, 4], [0, 4], [0, 10], [8, 10], [8, 0], [0, 0]], | ||
_: [[0, 0], [0, 1], [8, 1], [8, 0]], | ||
'.': [[0, 0], [0, 3], [3, 3], [3, 0]], | ||
}; | ||
// We map between the character and the internal name. | ||
var TTF_NAME_MAP = { _: 'underscore' }; | ||
var TTF_NAME_MAP = { _: 'underscore', '.': 'period' }; | ||
@@ -49,0 +88,0 @@ // The notdefGlyph always needs to be included. |
{ | ||
"name": "opentype.js", | ||
"description": "OpenType font parser", | ||
"version": "0.6.3", | ||
"version": "0.6.4", | ||
"author": { | ||
@@ -6,0 +6,0 @@ "name": "Frederik De Bleser", |
@@ -0,1 +1,8 @@ | ||
0.6.4 (June 30, 2016) | ||
========================= | ||
* Add X/Y scale options to compute a streched path of a glyph. | ||
* Correct reading/writing of font timestamps. | ||
* examples/generate-font-node.js now generates "full" Latin font. | ||
* Add OS/2 value options for weight, width and fsSelection. | ||
0.6.3 (May 10, 2016) | ||
@@ -2,0 +9,0 @@ ========================= |
@@ -46,2 +46,8 @@ // The Font object | ||
this.descender = options.descender; | ||
this.createdTimestamp = options.createdTimestamp; | ||
this.tables = { os2: { | ||
usWeightClass: options.weightClass || this.usWeightClasses.MEDIUM, | ||
usWidthClass: options.widthClass || this.usWidthClasses.MEDIUM, | ||
fsSelection: options.fsSelection || this.fsSelectionValues.REGULAR | ||
} }; | ||
} | ||
@@ -52,3 +58,3 @@ | ||
this.encoding = new encoding.DefaultEncoding(this); | ||
this.tables = {}; | ||
this.tables = this.tables || {}; | ||
} | ||
@@ -333,2 +339,39 @@ | ||
Font.prototype.fsSelectionValues = { | ||
ITALIC: 0x001, //1 | ||
UNDERSCORE: 0x002, //2 | ||
NEGATIVE: 0x004, //4 | ||
OUTLINED: 0x008, //8 | ||
STRIKEOUT: 0x010, //16 | ||
BOLD: 0x020, //32 | ||
REGULAR: 0x040, //64 | ||
USER_TYPO_METRICS: 0x080, //128 | ||
WWS: 0x100, //256 | ||
OBLIQUE: 0x200 //512 | ||
}; | ||
Font.prototype.usWidthClasses = { | ||
ULTRA_CONDENSED: 1, | ||
EXTRA_CONDENSED: 2, | ||
CONDENSED: 3, | ||
SEMI_CONDENSED: 4, | ||
MEDIUM: 5, | ||
SEMI_EXPANDED: 6, | ||
EXPANDED: 7, | ||
EXTRA_EXPANDED: 8, | ||
ULTRA_EXPANDED: 9 | ||
}; | ||
Font.prototype.usWeightClasses = { | ||
THIN: 100, | ||
EXTRA_LIGHT: 200, | ||
LIGHT: 300, | ||
NORMAL: 400, | ||
MEDIUM: 500, | ||
SEMI_BOLD: 600, | ||
BOLD: 700, | ||
EXTRA_BOLD: 800, | ||
BLACK: 900 | ||
}; | ||
exports.Font = Font; |
@@ -88,7 +88,12 @@ // The Glyph object | ||
// fontSize - Font size, in pixels (default: 72). | ||
Glyph.prototype.getPath = function(x, y, fontSize) { | ||
// options - xScale and yScale to strech the glyph. | ||
Glyph.prototype.getPath = function(x, y, fontSize, options) { | ||
x = x !== undefined ? x : 0; | ||
y = y !== undefined ? y : 0; | ||
options = options !== undefined ? options : {xScale: 1.0, yScale: 1.0}; | ||
fontSize = fontSize !== undefined ? fontSize : 72; | ||
var scale = 1 / this.path.unitsPerEm * fontSize; | ||
var xScale = options.xScale * scale; | ||
var yScale = options.yScale * scale; | ||
var p = new path.Path(); | ||
@@ -99,12 +104,12 @@ var commands = this.path.commands; | ||
if (cmd.type === 'M') { | ||
p.moveTo(x + (cmd.x * scale), y + (-cmd.y * scale)); | ||
p.moveTo(x + (cmd.x * xScale), y + (-cmd.y * yScale)); | ||
} else if (cmd.type === 'L') { | ||
p.lineTo(x + (cmd.x * scale), y + (-cmd.y * scale)); | ||
p.lineTo(x + (cmd.x * xScale), y + (-cmd.y * yScale)); | ||
} else if (cmd.type === 'Q') { | ||
p.quadraticCurveTo(x + (cmd.x1 * scale), y + (-cmd.y1 * scale), | ||
x + (cmd.x * scale), y + (-cmd.y * scale)); | ||
p.quadraticCurveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale), | ||
x + (cmd.x * xScale), y + (-cmd.y * yScale)); | ||
} else if (cmd.type === 'C') { | ||
p.curveTo(x + (cmd.x1 * scale), y + (-cmd.y1 * scale), | ||
x + (cmd.x2 * scale), y + (-cmd.y2 * scale), | ||
x + (cmd.x * scale), y + (-cmd.y * scale)); | ||
p.curveTo(x + (cmd.x1 * xScale), y + (-cmd.y1 * yScale), | ||
x + (cmd.x2 * xScale), y + (-cmd.y2 * yScale), | ||
x + (cmd.x * xScale), y + (-cmd.y * yScale)); | ||
} else if (cmd.type === 'Z') { | ||
@@ -198,4 +203,5 @@ p.closePath(); | ||
// fontSize - Font size, in pixels (default: 72). | ||
Glyph.prototype.draw = function(ctx, x, y, fontSize) { | ||
this.getPath(x, y, fontSize).draw(ctx); | ||
// options - xScale, yScale to strech the glyph | ||
Glyph.prototype.draw = function(ctx, x, y, fontSize, options) { | ||
this.getPath(x, y, fontSize, options).draw(ctx); | ||
}; | ||
@@ -202,0 +208,0 @@ |
@@ -182,4 +182,8 @@ // Parsing utility functions | ||
// only take the last 32 bits. | ||
// + Since until 2038 those bits will be filled by zeros we can ignore them. | ||
Parser.prototype.parseLongDateTime = function() { | ||
var v = exports.getULong(this.data, this.offset + this.relativeOffset + 4); | ||
// Substract seconds between 01/01/1904 and 01/01/1970 | ||
// to convert Apple Mac timstamp to Standard Unix timestamp | ||
v -= 2082844800; | ||
this.relativeOffset += 8; | ||
@@ -186,0 +190,0 @@ return v; |
@@ -36,2 +36,10 @@ // The `head` table contains global information about the font. | ||
function makeHeadTable(options) { | ||
// Apple Mac timestamp epoch is 01/01/1904 not 01/01/1970 | ||
var timestamp = Math.round(new Date().getTime() / 1000) + 2082844800; | ||
var createdTimestamp = timestamp; | ||
if (options.createdTimestamp) { | ||
createdTimestamp = options.createdTimestamp + 2082844800; | ||
} | ||
return new table.Table('head', [ | ||
@@ -44,4 +52,4 @@ {name: 'version', type: 'FIXED', value: 0x00010000}, | ||
{name: 'unitsPerEm', type: 'USHORT', value: 1000}, | ||
{name: 'created', type: 'LONGDATETIME', value: 0}, | ||
{name: 'modified', type: 'LONGDATETIME', value: 0}, | ||
{name: 'created', type: 'LONGDATETIME', value: createdTimestamp}, | ||
{name: 'modified', type: 'LONGDATETIME', value: timestamp}, | ||
{name: 'xMin', type: 'SHORT', value: 0}, | ||
@@ -48,0 +56,0 @@ {name: 'yMin', type: 'SHORT', value: 0}, |
@@ -151,8 +151,11 @@ // The `sfnt` wrapper provides organization for the tables in the font. | ||
if (typeof glyph.advanceWidth === 'undefined') { | ||
throw new Error('Glyph ' + glyph.name + ' (' + i + '): advanceWidth is required.'); | ||
if (isNaN(glyph.advanceWidth)) { | ||
throw new Error('Glyph ' + glyph.name + ' (' + i + '): advanceWidth is not a number.'); | ||
} | ||
if (firstCharIndex > unicode || firstCharIndex === null) { | ||
firstCharIndex = unicode; | ||
if (firstCharIndex > unicode || firstCharIndex === undefined) { | ||
// ignore .notdef char | ||
if (unicode > 0) { | ||
firstCharIndex = unicode; | ||
} | ||
} | ||
@@ -209,3 +212,4 @@ | ||
yMax: globals.yMax, | ||
lowestRecPPEM: 3 | ||
lowestRecPPEM: 3, | ||
createdTimestamp: font.createdTimestamp | ||
}); | ||
@@ -227,4 +231,4 @@ | ||
xAvgCharWidth: Math.round(globals.advanceWidthAvg), | ||
usWeightClass: 500, // Medium FIXME Make this configurable | ||
usWidthClass: 5, // Medium (normal) FIXME Make this configurable | ||
usWeightClass: font.tables.os2.usWeightClass, | ||
usWidthClass: font.tables.os2.usWidthClass, | ||
usFirstCharIndex: firstCharIndex, | ||
@@ -236,3 +240,3 @@ usLastCharIndex: lastCharIndex, | ||
ulUnicodeRange4: ulUnicodeRange4, | ||
fsSelection: 64, // REGULAR | ||
fsSelection: font.tables.os2.fsSelection, // REGULAR | ||
// See http://typophile.com/node/13081 for more info on vertical metrics. | ||
@@ -239,0 +243,0 @@ // We get metrics for typical characters (such as "x" for xHeight). |
@@ -110,4 +110,5 @@ // Data types used in the OpenType font file. | ||
// FIXME Implement LONGDATETIME | ||
encode.LONGDATETIME = function() { | ||
return [0, 0, 0, 0, 0, 0, 0, 0]; | ||
// Convert a 32-bit Apple Mac timestamp integer to a list of 8 bytes, 64-bit timestamp. | ||
encode.LONGDATETIME = function(v) { | ||
return [0, 0, 0, 0, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF]; | ||
}; | ||
@@ -114,0 +115,0 @@ |
@@ -65,5 +65,5 @@ 'use strict'; | ||
}); | ||
assert.throws(function() { font.toArrayBuffer(); }, /advanceWidth is required/); | ||
assert.throws(function() { font.toArrayBuffer(); }, /advanceWidth is not a number/); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
724052
65
13015