Socket
Socket
Sign inDemoInstall

opentype.js

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

opentype.js - npm Package Compare versions

Comparing version 0.4.6 to 0.4.7

.jscsrc

7

bin/server.js

@@ -26,6 +26,6 @@ #!/usr/bin/env node

'.ttf': 'font/otf',
'.otf': 'font/otf',
'.otf': 'font/otf'
};
http.createServer(function (req, res) {
http.createServer(function(req, res) {
var rewrite = '';

@@ -40,5 +40,6 @@ var url = req.url.substring(1);

}
console.log('HTTP', req.url, rewrite);
var filePath = './' + url;
fs.readFile(filePath, function (err, data) {
fs.readFile(filePath, function(err, data) {
if (err) {

@@ -45,0 +46,0 @@ res.writeHead(404, {'Content-Type': 'text/plain'});

{
"name": "opentype.js",
"version": "0.4.6",
"version": "0.4.7",
"main": "dist/opentype.js",

@@ -5,0 +5,0 @@ "keywords": [

{
"name": "opentype.js",
"description": "OpenType font parser",
"version": "0.4.6",
"version": "0.4.7",
"author": {

@@ -33,3 +33,3 @@ "name": "Frederik De Bleser",

"start": "mkdir -p build && bin/server.js",
"test": "jshint src",
"test": "jshint . && jscs .",
"browserify": "browserify src/opentype.js --bare --standalone opentype > dist/opentype.js",

@@ -42,2 +42,3 @@ "uglify": "browserify src/opentype.js --bare --standalone opentype -g uglifyify > dist/opentype.min.js",

"browserify": "^9.0.3",
"jscs": "^1.12.0",
"jshint": "^2.6.3",

@@ -47,5 +48,5 @@ "uglifyify": "^3.0.1",

},
"browser" : {
"fs": false
"browser": {
"fs": false
}
}

@@ -11,3 +11,3 @@ opentype.js

opentype.load('fonts/Roboto-Black.ttf', function (err, font) {
opentype.load('fonts/Roboto-Black.ttf', function(err, font) {
if (err) {

@@ -67,3 +67,3 @@ alert('Font could not be loaded: ' + err);

opentype.load('fonts/Roboto-Black.ttf', function (err, font) {
opentype.load('fonts/Roboto-Black.ttf', function(err, font) {
if (err) {

@@ -70,0 +70,0 @@ alert('Could not load font: ' + err);

@@ -7,3 +7,3 @@ // Run-time checking of preconditions.

// If not, it will throw an error.
exports.argument = function (predicate, message) {
exports.argument = function(predicate, message) {
if (!predicate) {

@@ -10,0 +10,0 @@ throw new Error(message);

@@ -131,10 +131,9 @@ // Glyph encoding

DefaultEncoding.prototype.charToGlyphIndex = function (c) {
var code, glyphs, i, glyph, j;
code = c.charCodeAt(0);
glyphs = this.font.glyphs;
DefaultEncoding.prototype.charToGlyphIndex = function(c) {
var code = c.charCodeAt(0);
var glyphs = this.font.glyphs;
if (glyphs) {
for (i = 0; i < glyphs.length; i += 1) {
glyph = glyphs[i];
for (j = 0; j < glyph.unicodes.length; j += 1) {
for (var i = 0; i < glyphs.length; i += 1) {
var glyph = glyphs[i];
for (var j = 0; j < glyph.unicodes.length; j += 1) {
if (glyph.unicodes[j] === code) {

@@ -154,3 +153,3 @@ return i;

CmapEncoding.prototype.charToGlyphIndex = function (c) {
CmapEncoding.prototype.charToGlyphIndex = function(c) {
return this.cmap.glyphIndexMap[c.charCodeAt(0)] || 0;

@@ -164,6 +163,5 @@ };

CffEncoding.prototype.charToGlyphIndex = function (s) {
var code, charName;
code = s.charCodeAt(0);
charName = this.encoding[code];
CffEncoding.prototype.charToGlyphIndex = function(s) {
var code = s.charCodeAt(0);
var charName = this.encoding[code];
return this.charset.indexOf(charName);

@@ -187,2 +185,3 @@ };

}
break;

@@ -194,2 +193,3 @@ case 2.5:

}
break;

@@ -202,7 +202,7 @@ case 3:

GlyphNames.prototype.nameToGlyphIndex = function (name) {
GlyphNames.prototype.nameToGlyphIndex = function(name) {
return this.names.indexOf(name);
};
GlyphNames.prototype.glyphIndexToName = function (gid) {
GlyphNames.prototype.glyphIndexToName = function(gid) {
return this.names[gid];

@@ -212,11 +212,12 @@ };

function addGlyphNames(font) {
var glyphIndexMap, charCodes, i, c, glyphIndex, glyph;
glyphIndexMap = font.tables.cmap.glyphIndexMap;
charCodes = Object.keys(glyphIndexMap);
for (i = 0; i < charCodes.length; i += 1) {
c = charCodes[i];
glyphIndex = glyphIndexMap[c];
var glyph;
var glyphIndexMap = font.tables.cmap.glyphIndexMap;
var charCodes = Object.keys(glyphIndexMap);
for (var i = 0; i < charCodes.length; i += 1) {
var c = charCodes[i];
var glyphIndex = glyphIndexMap[c];
glyph = font.glyphs[glyphIndex];
glyph.addUnicode(parseInt(c));
}
for (i = 0; i < font.glyphs.length; i += 1) {

@@ -223,0 +224,0 @@ glyph = font.glyphs[i];

@@ -14,2 +14,3 @@ // The Font object

options = options || {};
// OS X will complain if the names are empty, so we put a single space everywhere by default.

@@ -29,2 +30,4 @@ this.familyName = options.familyName || ' ';

this.unitsPerEm = options.unitsPerEm || 1000;
this.ascender = options.ascender;
this.descender = options.descender;
this.supported = true;

@@ -37,3 +40,3 @@ this.glyphs = options.glyphs || [];

// Check if the font has a glyph for the given character.
Font.prototype.hasChar = function (c) {
Font.prototype.hasChar = function(c) {
return this.encoding.charToGlyphIndex(c) !== null;

@@ -45,3 +48,3 @@ };

// the given character and a glyph; for complex scripts this might not be the case.
Font.prototype.charToGlyphIndex = function (s) {
Font.prototype.charToGlyphIndex = function(s) {
return this.encoding.charToGlyphIndex(s);

@@ -53,9 +56,10 @@ };

// the given character and a glyph; for complex scripts this might not be the case.
Font.prototype.charToGlyph = function (c) {
var glyphIndex, glyph;
glyphIndex = this.charToGlyphIndex(c);
glyph = this.glyphs[glyphIndex];
Font.prototype.charToGlyph = function(c) {
var glyphIndex = this.charToGlyphIndex(c);
var glyph = this.glyphs[glyphIndex];
if (!glyph) {
glyph = this.glyphs[0]; // .notdef
// .notdef
glyph = this.glyphs[0];
}
return glyph;

@@ -68,30 +72,32 @@ };

// length of the given string.
Font.prototype.stringToGlyphs = function (s) {
var i, c, glyphs;
glyphs = [];
for (i = 0; i < s.length; i += 1) {
c = s[i];
Font.prototype.stringToGlyphs = function(s) {
var glyphs = [];
for (var i = 0; i < s.length; i += 1) {
var c = s[i];
glyphs.push(this.charToGlyph(c));
}
return glyphs;
};
Font.prototype.nameToGlyphIndex = function (name) {
Font.prototype.nameToGlyphIndex = function(name) {
return this.glyphNames.nameToGlyphIndex(name);
};
Font.prototype.nameToGlyph = function (name) {
var glyphIndex, glyph;
glyphIndex = this.nametoGlyphIndex(name);
glyph = this.glyphs[glyphIndex];
Font.prototype.nameToGlyph = function(name) {
var glyphIndex = this.nametoGlyphIndex(name);
var glyph = this.glyphs[glyphIndex];
if (!glyph) {
glyph = this.glyphs[0]; // .notdef
// .notdef
glyph = this.glyphs[0];
}
return glyph;
};
Font.prototype.glyphIndexToName = function (gid) {
Font.prototype.glyphIndexToName = function(gid) {
if (!this.glyphNames.glyphIndexToName) {
return '';
}
return this.glyphNames.glyphIndexToName(gid);

@@ -104,3 +110,3 @@ };

// between glyphs.
Font.prototype.getKerningValue = function (leftGlyph, rightGlyph) {
Font.prototype.getKerningValue = function(leftGlyph, rightGlyph) {
leftGlyph = leftGlyph.index || leftGlyph;

@@ -115,7 +121,7 @@ rightGlyph = rightGlyph.index || rightGlyph;

// The callback gets `(glyph, x, y, fontSize, options)`.
Font.prototype.forEachGlyph = function (text, x, y, fontSize, options, callback) {
var kerning, fontScale, glyphs, i, glyph, kerningValue;
Font.prototype.forEachGlyph = function(text, x, y, fontSize, options, callback) {
if (!this.supported) {
return;
}
x = x !== undefined ? x : 0;

@@ -125,7 +131,7 @@ y = y !== undefined ? y : 0;

options = options || {};
kerning = options.kerning === undefined ? true : options.kerning;
fontScale = 1 / this.unitsPerEm * fontSize;
glyphs = this.stringToGlyphs(text);
for (i = 0; i < glyphs.length; i += 1) {
glyph = glyphs[i];
var kerning = options.kerning === undefined ? true : options.kerning;
var fontScale = 1 / this.unitsPerEm * fontSize;
var glyphs = this.stringToGlyphs(text);
for (var i = 0; i < glyphs.length; i += 1) {
var glyph = glyphs[i];
callback(glyph, x, y, fontSize, options);

@@ -135,4 +141,5 @@ if (glyph.advanceWidth) {

}
if (kerning && i < glyphs.length - 1) {
kerningValue = this.getKerningValue(glyph, glyphs[i + 1]);
var kerningValue = this.getKerningValue(glyph, glyphs[i + 1]);
x += kerningValue * fontScale;

@@ -153,8 +160,9 @@ }

// Returns a Path object.
Font.prototype.getPath = function (text, x, y, fontSize, options) {
Font.prototype.getPath = function(text, x, y, fontSize, options) {
var fullPath = new path.Path();
this.forEachGlyph(text, x, y, fontSize, options, function (glyph, gX, gY, gFontSize) {
this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
var glyphPath = glyph.getPath(gX, gY, gFontSize);
fullPath.extend(glyphPath);
});
return fullPath;

@@ -172,3 +180,3 @@ };

// - kerning - Whether to take kerning information into account. (default: true)
Font.prototype.draw = function (ctx, text, x, y, fontSize, options) {
Font.prototype.draw = function(ctx, text, x, y, fontSize, options) {
this.getPath(text, x, y, fontSize, options).draw(ctx);

@@ -187,4 +195,4 @@ };

// - kerning - Whether to take kerning information into account. (default: true)
Font.prototype.drawPoints = function (ctx, text, x, y, fontSize, options) {
this.forEachGlyph(text, x, y, fontSize, options, function (glyph, gX, gY, gFontSize) {
Font.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) {
this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
glyph.drawPoints(ctx, gX, gY, gFontSize);

@@ -206,4 +214,4 @@ });

// - kerning - Whether to take kerning information into account. (default: true)
Font.prototype.drawMetrics = function (ctx, text, x, y, fontSize, options) {
this.forEachGlyph(text, x, y, fontSize, options, function (glyph, gX, gY, gFontSize) {
Font.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) {
this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
glyph.drawMetrics(ctx, gX, gY, gFontSize);

@@ -214,5 +222,5 @@ });

// Validate
Font.prototype.validate = function () {
Font.prototype.validate = function() {
var warnings = [];
var font = this;
var _this = this;

@@ -226,3 +234,3 @@ function assert(predicate, message) {

function assertStringAttribute(attrName) {
assert(font[attrName] && font[attrName].trim().length > 0, 'No ' + attrName + ' specified.');
assert(_this[attrName] && _this[attrName].trim().length > 0, 'No ' + attrName + ' specified.');
}

@@ -243,7 +251,7 @@

// This structure contains all the necessary tables and metadata to create a binary OTF file.
Font.prototype.toTables = function () {
Font.prototype.toTables = function() {
return sfnt.fontToTable(this);
};
Font.prototype.toBuffer = function () {
Font.prototype.toBuffer = function() {
var sfntTable = this.toTables();

@@ -256,2 +264,3 @@ var bytes = sfntTable.encode();

}
return buffer;

@@ -261,3 +270,3 @@ };

// Initiate a download of the OpenType font.
Font.prototype.download = function () {
Font.prototype.download = function() {
var fileName = this.familyName.replace(/\s/g, '') + '-' + this.styleName + '.otf';

@@ -267,5 +276,5 @@ var buffer = this.toBuffer();

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.TEMPORARY, buffer.byteLength, function (fs) {
fs.root.getFile(fileName, {create: true}, function (fileEntry) {
fileEntry.createWriter(function (writer) {
window.requestFileSystem(window.TEMPORARY, buffer.byteLength, function(fs) {
fs.root.getFile(fileName, {create: true}, function(fileEntry) {
fileEntry.createWriter(function(writer) {
var dataView = new DataView(buffer);

@@ -275,9 +284,11 @@ var blob = new Blob([dataView], {type: 'font/opentype'});

writer.addEventListener('writeend', function () {
writer.addEventListener('writeend', function() {
// Navigating to the file will download it.
location.href = fileEntry.toURL();
}, false);
}, false);
});
});
}, function (err) {
},
function(err) {
throw err;

@@ -284,0 +295,0 @@ });

@@ -28,6 +28,7 @@ // The Glyph object

Glyph.prototype.addUnicode = function (unicode) {
Glyph.prototype.addUnicode = function(unicode) {
if (this.unicodes.length === 0) {
this.unicode = unicode;
}
this.unicodes.push(unicode);

@@ -41,12 +42,11 @@ };

// fontSize - Font size, in pixels (default: 72).
Glyph.prototype.getPath = function (x, y, fontSize) {
var scale, p, commands, cmd;
Glyph.prototype.getPath = function(x, y, fontSize) {
x = x !== undefined ? x : 0;
y = y !== undefined ? y : 0;
fontSize = fontSize !== undefined ? fontSize : 72;
scale = 1 / this.font.unitsPerEm * fontSize;
p = new path.Path();
commands = this.path.commands;
var scale = 1 / this.font.unitsPerEm * fontSize;
var p = new path.Path();
var commands = this.path.commands;
for (var i = 0; i < commands.length; i += 1) {
cmd = commands[i];
var cmd = commands[i];
if (cmd.type === 'M') {

@@ -67,2 +67,3 @@ p.moveTo(x + (cmd.x * scale), y + (-cmd.y * scale));

}
return p;

@@ -74,11 +75,11 @@ };

// provide raw access to the TrueType glyph outlines.
Glyph.prototype.getContours = function () {
var contours, currentContour, i, pt;
Glyph.prototype.getContours = function() {
if (this.points === undefined) {
return [];
}
contours = [];
currentContour = [];
for (i = 0; i < this.points.length; i += 1) {
pt = this.points[i];
var contours = [];
var currentContour = [];
for (var i = 0; i < this.points.length; i += 1) {
var pt = this.points[i];
currentContour.push(pt);

@@ -90,2 +91,3 @@ if (pt.lastPointOfContour) {

}
check.argument(currentContour.length === 0, 'There are still points left in the current contour.');

@@ -96,3 +98,3 @@ return contours;

// Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph.
Glyph.prototype.getMetrics = function () {
Glyph.prototype.getMetrics = function() {
var commands = this.path.commands;

@@ -107,2 +109,3 @@ var xCoords = [];

}
if (cmd.type === 'Q' || cmd.type === 'C') {

@@ -112,2 +115,3 @@ xCoords.push(cmd.x1);

}
if (cmd.type === 'C') {

@@ -118,2 +122,3 @@ xCoords.push(cmd.x2);

}
var metrics = {

@@ -136,3 +141,3 @@ xMin: Math.min.apply(null, xCoords),

// fontSize - Font size, in pixels (default: 72).
Glyph.prototype.draw = function (ctx, x, y, fontSize) {
Glyph.prototype.draw = function(ctx, x, y, fontSize) {
this.getPath(x, y, fontSize).draw(ctx);

@@ -148,11 +153,12 @@ };

// fontSize - Font size, in pixels (default: 72).
Glyph.prototype.drawPoints = function (ctx, x, y, fontSize) {
Glyph.prototype.drawPoints = function(ctx, x, y, fontSize) {
function drawCircles(l, x, y, scale) {
var j, PI_SQ = Math.PI * 2;
var PI_SQ = Math.PI * 2;
ctx.beginPath();
for (j = 0; j < l.length; j += 1) {
for (var j = 0; j < l.length; j += 1) {
ctx.moveTo(x + (l[j].x * scale), y + (l[j].y * scale));
ctx.arc(x + (l[j].x * scale), y + (l[j].y * scale), 2, 0, PI_SQ, false);
}
ctx.closePath();

@@ -162,19 +168,20 @@ ctx.fill();

var scale, i, blueCircles, redCircles, path, cmd;
x = x !== undefined ? x : 0;
y = y !== undefined ? y : 0;
fontSize = fontSize !== undefined ? fontSize : 24;
scale = 1 / this.font.unitsPerEm * fontSize;
var scale = 1 / this.font.unitsPerEm * fontSize;
blueCircles = [];
redCircles = [];
path = this.path;
for (i = 0; i < path.commands.length; i += 1) {
cmd = path.commands[i];
var blueCircles = [];
var redCircles = [];
var path = this.path;
for (var i = 0; i < path.commands.length; i += 1) {
var cmd = path.commands[i];
if (cmd.x !== undefined) {
blueCircles.push({x: cmd.x, y: -cmd.y});
}
if (cmd.x1 !== undefined) {
redCircles.push({x: cmd.x1, y: -cmd.y1});
}
if (cmd.x2 !== undefined) {

@@ -200,3 +207,3 @@ redCircles.push({x: cmd.x2, y: -cmd.y2});

// fontSize - Font size, in pixels (default: 72).
Glyph.prototype.drawMetrics = function (ctx, x, y, fontSize) {
Glyph.prototype.drawMetrics = function(ctx, x, y, fontSize) {
var scale;

@@ -208,2 +215,3 @@ x = x !== undefined ? x : 0;

ctx.lineWidth = 1;
// Draw the origin

@@ -213,2 +221,3 @@ ctx.strokeStyle = 'black';

draw.line(ctx, -10000, y, 10000, y);
// Draw the glyph box

@@ -220,2 +229,3 @@ ctx.strokeStyle = 'blue';

draw.line(ctx, -10000, y + (-this.yMax * scale), 10000, y + (-this.yMax * scale));
// Draw the advance width

@@ -222,0 +232,0 @@ ctx.strokeStyle = 'green';

@@ -34,7 +34,5 @@ // opentype.js

function toArrayBuffer(buffer) {
var i,
arrayBuffer = new ArrayBuffer(buffer.length),
data = new Uint8Array(arrayBuffer);
for (i = 0; i < buffer.length; i += 1) {
var arrayBuffer = new ArrayBuffer(buffer.length);
var data = new Uint8Array(arrayBuffer);
for (var i = 0; i < buffer.length; i += 1) {
data[i] = buffer[i];

@@ -48,3 +46,3 @@ }

var fs = require('fs');
fs.readFile(path, function (err, buffer) {
fs.readFile(path, function(err, buffer) {
if (err) {

@@ -62,8 +60,10 @@ return callback(err.message);

request.responseType = 'arraybuffer';
request.onload = function () {
request.onload = function() {
if (request.status !== 200) {
return callback('Font could not be loaded: ' + request.statusText);
}
return callback(null, request.response);
};
request.send();

@@ -78,5 +78,10 @@ }

function parseBuffer(buffer) {
var font, data, version, numTables, i, p, tag, offset, hmtxOffset, glyfOffset, locaOffset,
cffOffset, kernOffset, gposOffset, indexToLocFormat, numGlyphs, locaTable,
shortVersion;
var indexToLocFormat;
var hmtxOffset;
var glyfOffset;
var locaOffset;
var cffOffset;
var kernOffset;
var gposOffset;
// OpenType fonts use big endian byte ordering.

@@ -86,6 +91,6 @@ // We can't rely on typed array view types, because they operate with the endianness of the host computer.

font = new _font.Font();
data = new DataView(buffer, 0);
var font = new _font.Font();
var data = new DataView(buffer, 0);
version = parse.getFixed(data, 0);
var version = parse.getFixed(data, 0);
if (version === 1.0) {

@@ -102,9 +107,9 @@ font.outlinesFormat = 'truetype';

numTables = parse.getUShort(data, 4);
var numTables = parse.getUShort(data, 4);
// Offset into the table records.
p = 12;
for (i = 0; i < numTables; i += 1) {
tag = parse.getTag(data, p);
offset = parse.getULong(data, p + 8);
var p = 12;
for (var i = 0; i < numTables; i += 1) {
var tag = parse.getTag(data, p);
var offset = parse.getULong(data, p + 8);
switch (tag) {

@@ -117,2 +122,3 @@ case 'cmap':

}
break;

@@ -135,3 +141,3 @@ case 'head':

font.tables.maxp = maxp.parse(data, offset);
font.numGlyphs = numGlyphs = font.tables.maxp.numGlyphs;
font.numGlyphs = font.tables.maxp.numGlyphs;
break;

@@ -170,4 +176,4 @@ case 'name':

if (glyfOffset && locaOffset) {
shortVersion = indexToLocFormat === 0;
locaTable = loca.parse(data, locaOffset, numGlyphs, shortVersion);
var shortVersion = indexToLocFormat === 0;
var locaTable = loca.parse(data, locaOffset, font.numGlyphs, shortVersion);
font.glyphs = glyf.parse(data, glyfOffset, locaTable, font);

@@ -189,2 +195,3 @@ hmtx.parse(data, hmtxOffset, font.numberOfHMetrics, font.numGlyphs, font.glyphs);

}
if (gposOffset) {

@@ -207,6 +214,7 @@ gpos.parse(data, gposOffset, font);

var loadFn = isNode ? loadFromFile : loadFromUrl;
loadFn(url, function (err, arrayBuffer) {
loadFn(url, function(err, arrayBuffer) {
if (err) {
return callback(err);
}
var font = parseBuffer(arrayBuffer);

@@ -216,2 +224,3 @@ if (!font.supported) {

}
return callback(null, font);

@@ -218,0 +227,0 @@ });

@@ -14,3 +14,3 @@ // Parsing utility functions

// The value is stored in big endian.
exports.getUShort = function (dataView, offset) {
exports.getUShort = function(dataView, offset) {
return dataView.getUint16(offset, false);

@@ -23,3 +23,3 @@ };

// The value is stored in big endian.
exports.getShort = function (dataView, offset) {
exports.getShort = function(dataView, offset) {
return dataView.getInt16(offset, false);

@@ -30,3 +30,3 @@ };

// The value is stored in big endian.
exports.getULong = function (dataView, offset) {
exports.getULong = function(dataView, offset) {
return dataView.getUint32(offset, false);

@@ -37,6 +37,5 @@ };

// The value is stored in big endian.
exports.getFixed = function (dataView, offset) {
var decimal, fraction;
decimal = dataView.getInt16(offset, false);
fraction = dataView.getUint16(offset + 2, false);
exports.getFixed = function(dataView, offset) {
var decimal = dataView.getInt16(offset, false);
var fraction = dataView.getUint16(offset + 2, false);
return decimal + fraction / 65535;

@@ -47,7 +46,8 @@ };

// Tags are used to identify tables.
exports.getTag = function (dataView, offset) {
var tag = '', i;
for (i = offset; i < offset + 4; i += 1) {
exports.getTag = function(dataView, offset) {
var tag = '';
for (var i = offset; i < offset + 4; i += 1) {
tag += String.fromCharCode(dataView.getInt8(i));
}
return tag;

@@ -58,9 +58,9 @@ };

// Offsets are 1 to 4 bytes in length, depending on the offSize argument.
exports.getOffset = function (dataView, offset, offSize) {
var i, v;
v = 0;
for (i = 0; i < offSize; i += 1) {
exports.getOffset = function(dataView, offset, offSize) {
var v = 0;
for (var i = 0; i < offSize; i += 1) {
v <<= 8;
v += dataView.getUint8(offset + i);
}
return v;

@@ -70,8 +70,8 @@ };

// Retrieve a number of bytes from start offset to the end offset from the DataView.
exports.getBytes = function (dataView, startOffset, endOffset) {
var bytes, i;
bytes = [];
for (i = startOffset; i < endOffset; i += 1) {
exports.getBytes = function(dataView, startOffset, endOffset) {
var bytes = [];
for (var i = startOffset; i < endOffset; i += 1) {
bytes.push(dataView.getUint8(i));
}
return bytes;

@@ -81,8 +81,8 @@ };

// Convert the list of bytes to a string.
exports.bytesToString = function (bytes) {
var s, i;
s = '';
for (i = 0; i < bytes.length; i += 1) {
exports.bytesToString = function(bytes) {
var s = '';
for (var i = 0; i < bytes.length; i += 1) {
s += String.fromCharCode(bytes[i]);
}
return s;

@@ -109,3 +109,3 @@ };

Parser.prototype.parseByte = function () {
Parser.prototype.parseByte = function() {
var v = this.data.getUint8(this.offset + this.relativeOffset);

@@ -116,3 +116,3 @@ this.relativeOffset += 1;

Parser.prototype.parseChar = function () {
Parser.prototype.parseChar = function() {
var v = this.data.getInt8(this.offset + this.relativeOffset);

@@ -125,3 +125,3 @@ this.relativeOffset += 1;

Parser.prototype.parseUShort = function () {
Parser.prototype.parseUShort = function() {
var v = this.data.getUint16(this.offset + this.relativeOffset);

@@ -131,2 +131,3 @@ this.relativeOffset += 2;

};
Parser.prototype.parseCard16 = Parser.prototype.parseUShort;

@@ -136,3 +137,3 @@ Parser.prototype.parseSID = Parser.prototype.parseUShort;

Parser.prototype.parseShort = function () {
Parser.prototype.parseShort = function() {
var v = this.data.getInt16(this.offset + this.relativeOffset);

@@ -143,3 +144,3 @@ this.relativeOffset += 2;

Parser.prototype.parseF2Dot14 = function () {
Parser.prototype.parseF2Dot14 = function() {
var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384;

@@ -150,3 +151,3 @@ this.relativeOffset += 2;

Parser.prototype.parseULong = function () {
Parser.prototype.parseULong = function() {
var v = exports.getULong(this.data, this.offset + this.relativeOffset);

@@ -157,3 +158,3 @@ this.relativeOffset += 4;

Parser.prototype.parseFixed = function () {
Parser.prototype.parseFixed = function() {
var v = exports.getFixed(this.data, this.offset + this.relativeOffset);

@@ -165,6 +166,6 @@ this.relativeOffset += 4;

Parser.prototype.parseOffset16List =
Parser.prototype.parseUShortList = function (count) {
var offsets = new Array(count),
dataView = this.data,
offset = this.offset + this.relativeOffset;
Parser.prototype.parseUShortList = function(count) {
var offsets = new Array(count);
var dataView = this.data;
var offset = this.offset + this.relativeOffset;
for (var i = 0; i < count; i++) {

@@ -174,2 +175,3 @@ offsets[i] = exports.getUShort(dataView, offset);

}
this.relativeOffset += count * 2;

@@ -179,6 +181,6 @@ return offsets;

Parser.prototype.parseString = function (length) {
var dataView = this.data,
offset = this.offset + this.relativeOffset,
string = '';
Parser.prototype.parseString = function(length) {
var dataView = this.data;
var offset = this.offset + this.relativeOffset;
var string = '';
this.relativeOffset += length;

@@ -188,6 +190,7 @@ for (var i = 0; i < length; i++) {

}
return string;
};
Parser.prototype.parseTag = function () {
Parser.prototype.parseTag = function() {
return this.parseString(4);

@@ -213,2 +216,3 @@ };

var major = exports.getUShort(this.data, this.offset + this.relativeOffset);
// How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1

@@ -221,6 +225,7 @@ // This returns the correct number if minor = 0xN000 where N is 0-9

Parser.prototype.skip = function (type, amount) {
Parser.prototype.skip = function(type, amount) {
if (amount === undefined) {
amount = 1;
}
this.relativeOffset += typeOffsets[type] * amount;

@@ -227,0 +232,0 @@ };

@@ -14,3 +14,3 @@ // Geometric objects

Path.prototype.moveTo = function (x, y) {
Path.prototype.moveTo = function(x, y) {
this.commands.push({

@@ -23,3 +23,3 @@ type: 'M',

Path.prototype.lineTo = function (x, y) {
Path.prototype.lineTo = function(x, y) {
this.commands.push({

@@ -32,3 +32,3 @@ type: 'L',

Path.prototype.curveTo = Path.prototype.bezierCurveTo = function (x1, y1, x2, y2, x, y) {
Path.prototype.curveTo = Path.prototype.bezierCurveTo = function(x1, y1, x2, y2, x, y) {
this.commands.push({

@@ -45,3 +45,3 @@ type: 'C',

Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function (x1, y1, x, y) {
Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function(x1, y1, x, y) {
this.commands.push({

@@ -56,3 +56,3 @@ type: 'Q',

Path.prototype.close = Path.prototype.closePath = function () {
Path.prototype.close = Path.prototype.closePath = function() {
this.commands.push({

@@ -64,6 +64,7 @@ type: 'Z'

// Add the given path or list of commands to the commands of this path.
Path.prototype.extend = function (pathOrCommands) {
Path.prototype.extend = function(pathOrCommands) {
if (pathOrCommands.commands) {
pathOrCommands = pathOrCommands.commands;
}
Array.prototype.push.apply(this.commands, pathOrCommands);

@@ -73,7 +74,6 @@ };

// Draw the path to a 2D context.
Path.prototype.draw = function (ctx) {
var i, cmd;
Path.prototype.draw = function(ctx) {
ctx.beginPath();
for (i = 0; i < this.commands.length; i += 1) {
cmd = this.commands[i];
for (var i = 0; i < this.commands.length; i += 1) {
var cmd = this.commands[i];
if (cmd.type === 'M') {

@@ -91,2 +91,3 @@ ctx.moveTo(cmd.x, cmd.y);

}
if (this.fill) {

@@ -96,2 +97,3 @@ ctx.fillStyle = this.fill;

}
if (this.stroke) {

@@ -108,3 +110,3 @@ ctx.strokeStyle = this.stroke;

// - decimalPlaces: The amount of decimal places for floating-point values (default: 2)
Path.prototype.toPathData = function (decimalPlaces) {
Path.prototype.toPathData = function(decimalPlaces) {
decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2;

@@ -127,4 +129,6 @@

}
s += floatToString(v);
}
return s;

@@ -148,2 +152,3 @@ }

}
return d;

@@ -155,3 +160,3 @@ };

// - decimalPlaces: The amount of decimal places for floating-point values (default: 2)
Path.prototype.toSVG = function (decimalPlaces) {
Path.prototype.toSVG = function(decimalPlaces) {
var svg = '<path d="';

@@ -167,5 +172,7 @@ svg += this.toPathData(decimalPlaces);

}
if (this.stroke) {
svg += ' stroke="' + this.stroke + '" stroke-width="' + this.strokeWidth + '"';
}
svg += '/>';

@@ -172,0 +179,0 @@ return svg;

@@ -15,2 +15,3 @@ // Table metadata

}
this.tableName = tableName;

@@ -30,3 +31,3 @@ this.fields = fields;

Table.prototype.sizeOf = function () {
Table.prototype.sizeOf = function() {
var v = 0;

@@ -39,2 +40,3 @@ for (var i = 0; i < this.fields.length; i += 1) {

}
if (typeof value.sizeOf === 'function') {

@@ -48,6 +50,7 @@ v += value.sizeOf();

}
return v;
};
Table.prototype.encode = function () {
Table.prototype.encode = function() {
return encode.TABLE(this);

@@ -54,0 +57,0 @@ };

@@ -22,2 +22,3 @@ // The `CFF` table contains the glyph outlines in PostScript format.

}
for (var i = 0; i < a.length; i += 1) {

@@ -28,2 +29,3 @@ if (!equals(a[i], b[i])) {

}
return true;

@@ -38,10 +40,13 @@ } else {

function parseCFFIndex(data, start, conversionFn) {
var offsets, objects, count, endOffset, offsetSize, objectOffset, pos, i, value;
offsets = [];
objects = [];
count = parse.getCard16(data, start);
//var i, objectOffset, endOffset;
var offsets = [];
var objects = [];
var count = parse.getCard16(data, start);
var i;
var objectOffset;
var endOffset;
if (count !== 0) {
offsetSize = parse.getByte(data, start + 2);
var offsetSize = parse.getByte(data, start + 2);
objectOffset = start + ((count + 1) * offsetSize) + 2;
pos = start + 3;
var pos = start + 3;
for (i = 0; i < count + 1; i += 1) {

@@ -51,2 +56,3 @@ offsets.push(parse.getOffset(data, pos, offsetSize));

}
// The total size of the index array is 4 header bytes + the value of the last offset.

@@ -57,9 +63,12 @@ endOffset = objectOffset + offsets[count];

}
for (i = 0; i < offsets.length - 1; i += 1) {
value = parse.getBytes(data, objectOffset + offsets[i], objectOffset + offsets[i + 1]);
var value = parse.getBytes(data, objectOffset + offsets[i], objectOffset + offsets[i + 1]);
if (conversionFn) {
value = conversionFn(value);
}
objects.push(value);
}
return {objects: objects, startOffset: start, endOffset: endOffset};

@@ -70,10 +79,9 @@ }

function parseFloatOperand(parser) {
var s, eof, lookup, b, n1, n2;
s = '';
eof = 15;
lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];
var s = '';
var eof = 15;
var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];
while (true) {
b = parser.parseByte();
n1 = b >> 4;
n2 = b & 15;
var b = parser.parseByte();
var n1 = b >> 4;
var n2 = b & 15;

@@ -83,2 +91,3 @@ if (n1 === eof) {

}
s += lookup[n1];

@@ -89,4 +98,6 @@

}
s += lookup[n2];
}
return parseFloat(s);

@@ -97,3 +108,6 @@ }

function parseOperand(parser, b0) {
var b1, b2, b3, b4;
var b1;
var b2;
var b3;
var b4;
if (b0 === 28) {

@@ -104,2 +118,3 @@ b1 = parser.parseByte();

}
if (b0 === 29) {

@@ -112,8 +127,11 @@ b1 = parser.parseByte();

}
if (b0 === 30) {
return parseFloatOperand(parser);
}
if (b0 >= 32 && b0 <= 246) {
return b0 - 139;
}
if (b0 >= 247 && b0 <= 250) {

@@ -123,2 +141,3 @@ b1 = parser.parseByte();

}
if (b0 >= 251 && b0 <= 254) {

@@ -128,2 +147,3 @@ b1 = parser.parseByte();

}
throw new Error('Invalid b0 ' + b0);

@@ -135,7 +155,7 @@ }

function entriesToObject(entries) {
var o, key, values, i, value;
o = {};
for (i = 0; i < entries.length; i += 1) {
key = entries[i][0];
values = entries[i][1];
var o = {};
for (var i = 0; i < entries.length; i += 1) {
var key = entries[i][0];
var values = entries[i][1];
var value;
if (values.length === 1) {

@@ -146,7 +166,10 @@ value = values[0];

}
if (o.hasOwnProperty(key)) {
throw new Error('Object ' + o + ' already has key ' + key);
}
o[key] = value;
}
return o;

@@ -158,11 +181,11 @@ }

function parseCFFDict(data, start, size) {
var parser, entries, operands, op;
start = start !== undefined ? start : 0;
parser = new parse.Parser(data, start);
entries = [];
operands = [];
var parser = new parse.Parser(data, start);
var entries = [];
var operands = [];
size = size !== undefined ? size : data.length;
while (parser.relativeOffset < size) {
op = parser.parseByte();
var op = parser.parseByte();
// The first byte for each dict item distinguishes between operator (key) and operand (value).

@@ -175,2 +198,3 @@ // Values <= 21 are operators.

}
entries.push([op, operands]);

@@ -184,2 +208,3 @@ operands = [];

}
return entriesToObject(entries);

@@ -196,2 +221,3 @@ }

}
return index;

@@ -203,17 +229,20 @@ }

function interpretDict(dict, meta, strings) {
var i, m, value, newDict;
newDict = {};
var newDict = {};
// Because we also want to include missing values, we start out from the meta list
// and lookup values in the dict.
for (i = 0; i < meta.length; i += 1) {
m = meta[i];
value = dict[m.op];
for (var i = 0; i < meta.length; i += 1) {
var m = meta[i];
var value = dict[m.op];
if (value === undefined) {
value = m.value !== undefined ? m.value : null;
}
if (m.type === 'SID') {
value = getCFFString(strings, value);
}
newDict[m.name] = value;
}
return newDict;

@@ -267,4 +296,3 @@ }

function parseCFFTopDict(data, strings) {
var dict;
dict = parseCFFDict(data, 0, data.byteLength);
var dict = parseCFFDict(data, 0, data.byteLength);
return interpretDict(dict, TOP_DICT_META, strings);

@@ -275,4 +303,3 @@ }

function parseCFFPrivateDict(data, start, size, strings) {
var dict;
dict = parseCFFDict(data, start, size);
var dict = parseCFFDict(data, start, size);
return interpretDict(dict, PRIVATE_DICT_META, strings);

@@ -285,9 +312,12 @@ }

function parseCFFCharset(data, start, nGlyphs, strings) {
var parser, format, charset, i, sid, count;
parser = new parse.Parser(data, start);
var i;
var sid;
var count;
var parser = new parse.Parser(data, start);
// The .notdef glyph is not included, so subtract 1.
nGlyphs -= 1;
charset = ['.notdef'];
var charset = ['.notdef'];
format = parser.parseCard8();
var format = parser.parseCard8();
if (format === 0) {

@@ -326,8 +356,9 @@ for (i = 0; i < nGlyphs; i += 1) {

function parseCFFEncoding(data, start, charset) {
var enc, parser, format, nCodes, i, code, nRanges, first, nLeft, j;
enc = {};
parser = new parse.Parser(data, start);
format = parser.parseCard8();
var i;
var code;
var enc = {};
var parser = new parse.Parser(data, start);
var format = parser.parseCard8();
if (format === 0) {
nCodes = parser.parseCard8();
var nCodes = parser.parseCard8();
for (i = 0; i < nCodes; i += 1) {

@@ -338,8 +369,8 @@ code = parser.parseCard8();

} else if (format === 1) {
nRanges = parser.parseCard8();
var nRanges = parser.parseCard8();
code = 1;
for (i = 0; i < nRanges; i += 1) {
first = parser.parseCard8();
nLeft = parser.parseCard8();
for (j = first; j <= first + nLeft; j += 1) {
var first = parser.parseCard8();
var nLeft = parser.parseCard8();
for (var j = first; j <= first + nLeft; j += 1) {
enc[j] = code;

@@ -352,2 +383,3 @@ code += 1;

}
return new encoding.CffEncoding(enc, charset);

@@ -360,10 +392,14 @@ }

function parseCFFCharstring(code, font, index) {
var p, glyph, stack, nStems, haveWidth, width, open, x, y, c1x, c1y, c2x, c2y, v;
p = new path.Path();
stack = [];
nStems = 0;
haveWidth = false;
width = font.defaultWidthX;
open = false;
x = y = 0;
var c1x;
var c1y;
var c2x;
var c2y;
var p = new path.Path();
var stack = [];
var nStems = 0;
var haveWidth = false;
var width = font.defaultWidthX;
var open = false;
var x = 0;
var y = 0;

@@ -374,2 +410,3 @@ function newContour(x, y) {

}
p.moveTo(x, y);

@@ -381,2 +418,3 @@ open = true;

var hasWidthArg;
// The number of stem operators on the stack is always even.

@@ -388,2 +426,3 @@ // If the value is uneven, that means a width is specified.

}
nStems += stack.length >> 1;

@@ -395,6 +434,18 @@ stack.length = 0;

function parse(code) {
var i, b1, b2, b3, b4, codeIndex, subrCode;
i = 0;
var b1;
var b2;
var b3;
var b4;
var codeIndex;
var subrCode;
var jpx;
var jpy;
var c3x;
var c3y;
var c4x;
var c4y;
var i = 0;
while (i < code.length) {
v = code[i];
var v = code[i];
i += 1;

@@ -413,2 +464,3 @@ switch (v) {

}
y += stack.pop();

@@ -423,2 +475,3 @@ newContour(x, y);

}
break;

@@ -432,5 +485,7 @@ case 6: // hlineto

}
y += stack.shift();
p.lineTo(x, y);
}
break;

@@ -444,5 +499,7 @@ case 7: // vlineto

}
x += stack.shift();
p.lineTo(x, y);
}
break;

@@ -459,2 +516,3 @@ case 8: // rrcurveto

}
break;

@@ -467,2 +525,3 @@ case 10: // callsubr

}
break;

@@ -474,3 +533,2 @@ case 11: // return

i += 1;
var jpx, jpy, c3x, c3y, c4x, c4y, fd;
switch (v) {

@@ -491,3 +549,3 @@ case 35: // flex

y = c4y + stack.shift(); // dy6
fd = stack.shift(); // flex depth
stack.shift(); // flex depth
p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);

@@ -509,3 +567,2 @@ p.curveTo(c3x, c3y, c4x, c4y, x, y);

x = c4x + stack.shift(); // dx6
// y = y; // dy6
p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);

@@ -527,3 +584,2 @@ p.curveTo(c3x, c3y, c4x, c4y, x, y);

x = c4x + stack.shift(); // dx6
// y = y; // dy6
p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);

@@ -544,8 +600,8 @@ p.curveTo(c3x, c3y, c4x, c4y, x, y);

c4y = c3y + stack.shift(); // dy5
if (Math.abs(c4x - x) > Math.abs(c4y - y)) {
x = c4x + stack.shift(); // d6
x = c4x + stack.shift();
} else {
y = c4y + stack.shift(); // d6
y = c4y + stack.shift();
}
p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);

@@ -564,2 +620,3 @@ p.curveTo(c3x, c3y, c4x, c4y, x, y);

}
if (open) {

@@ -569,2 +626,3 @@ p.closePath();

}
break;

@@ -584,2 +642,3 @@ case 18: // hstemhm

}
y += stack.pop();

@@ -594,2 +653,3 @@ x += stack.pop();

}
x += stack.pop();

@@ -611,2 +671,3 @@ newContour(x, y);

}
x += stack.shift();

@@ -622,2 +683,3 @@ y += stack.shift();

}
c1x = x + stack.shift();

@@ -635,2 +697,3 @@ c1y = y + stack.shift();

}
while (stack.length > 0) {

@@ -645,2 +708,3 @@ c1x = x;

}
break;

@@ -651,2 +715,3 @@ case 27: // hhcurveto

}
while (stack.length > 0) {

@@ -661,2 +726,3 @@ c1x = x + stack.shift();

}
break;

@@ -675,2 +741,3 @@ case 28: // shortint

}
break;

@@ -689,2 +756,3 @@ case 30: // vhcurveto

}
c1x = x + stack.shift();

@@ -698,2 +766,3 @@ c1y = y;

}
break;

@@ -712,2 +781,3 @@ case 31: // hvcurveto

}
c1x = x;

@@ -721,2 +791,3 @@ c1y = y + stack.shift();

}
break;

@@ -749,3 +820,3 @@ default:

parse(code);
glyph = new _glyph.Glyph({font: font, index: index});
var glyph = new _glyph.Glyph({font: font, index: index});
glyph.path = p;

@@ -767,2 +838,3 @@ glyph.advanceWidth = width;

}
return bias;

@@ -773,10 +845,8 @@ }

function parseCFFTable(data, start, font) {
var header, nameIndex, topDictIndex, stringIndex, globalSubrIndex, topDict, privateDictOffset, privateDict,
subrOffset, subrIndex, charString, charStringsIndex, charset, i;
font.tables.cff = {};
header = parseCFFHeader(data, start);
nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);
topDictIndex = parseCFFIndex(data, nameIndex.endOffset);
stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString);
globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);
var header = parseCFFHeader(data, start);
var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);
var topDictIndex = parseCFFIndex(data, nameIndex.endOffset);
var stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString);
var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);
font.gsubrs = globalSubrIndex.objects;

@@ -786,7 +856,7 @@ font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);

var topDictData = new DataView(new Uint8Array(topDictIndex.objects[0]).buffer);
topDict = parseCFFTopDict(topDictData, stringIndex.objects);
var topDict = parseCFFTopDict(topDictData, stringIndex.objects);
font.tables.cff.topDict = topDict;
privateDictOffset = start + topDict['private'][1];
privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict['private'][0], stringIndex.objects);
var privateDictOffset = start + topDict['private'][1];
var privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict['private'][0], stringIndex.objects);
font.defaultWidthX = privateDict.defaultWidthX;

@@ -796,4 +866,4 @@ font.nominalWidthX = privateDict.nominalWidthX;

if (privateDict.subrs !== 0) {
subrOffset = privateDictOffset + privateDict.subrs;
subrIndex = parseCFFIndex(data, subrOffset);
var subrOffset = privateDictOffset + privateDict.subrs;
var subrIndex = parseCFFIndex(data, subrOffset);
font.subrs = subrIndex.objects;

@@ -807,6 +877,6 @@ font.subrsBias = calcCFFSubroutineBias(font.subrs);

// Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.
charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);
var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);
font.nGlyphs = charStringsIndex.objects.length;
charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects);
var charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects);
if (topDict.encoding === 0) { // Standard encoding

@@ -819,2 +889,3 @@ font.cffEncoding = new encoding.CffEncoding(encoding.cffStandardEncoding, charset);

}
// Prefer the CMAP encoding to the CFF encoding.

@@ -824,4 +895,4 @@ font.encoding = font.encoding || font.cffEncoding;

font.glyphs = [];
for (i = 0; i < font.nGlyphs; i += 1) {
charString = charStringsIndex.objects[i];
for (var i = 0; i < font.nGlyphs; i += 1) {
var charString = charStringsIndex.objects[i];
font.glyphs.push(parseCFFCharstring(charString, font, i));

@@ -831,12 +902,13 @@ }

// Convert a string to a String ID (SID).
// The list of strings is modified in place.
function encodeString(s, strings) {
var i, sid;
var sid;
// Is the string in the CFF standard strings?
i = encoding.cffStandardStrings.indexOf(s);
var i = encoding.cffStandardStrings.indexOf(s);
if (i >= 0) {
sid = i;
}
// Is the string already in the string index?

@@ -850,2 +922,3 @@ i = strings.indexOf(s);

}
return sid;

@@ -871,2 +944,3 @@ }

}
return t;

@@ -877,6 +951,6 @@ }

function makeDict(meta, attrs, strings) {
var m = {}, i, entry, value;
for (i = 0; i < meta.length; i += 1) {
entry = meta[i];
value = attrs[entry.name];
var m = {};
for (var i = 0; i < meta.length; i += 1) {
var entry = meta[i];
var value = attrs[entry.name];
if (value !== undefined && !equals(value, entry.value)) {

@@ -886,5 +960,7 @@ if (entry.type === 'SID') {

}
m[entry.op] = {name: entry.name, type: entry.type, value: value};
}
}
return m;

@@ -918,2 +994,3 @@ }

}
return t;

@@ -938,2 +1015,3 @@ }

}
return t;

@@ -943,8 +1021,11 @@ }

function glyphToOps(glyph) {
var ops = [], path = glyph.path, x, y, i, cmd, dx, dy, dx1, dy1, dx2, dy2;
var ops = [];
var path = glyph.path;
ops.push({name: 'width', type: 'NUMBER', value: glyph.advanceWidth});
x = 0;
y = 0;
for (i = 0; i < path.commands.length; i += 1) {
cmd = path.commands[i];
var x = 0;
var y = 0;
for (var i = 0; i < path.commands.length; i += 1) {
var dx;
var dy;
var cmd = path.commands[i];
if (cmd.type === 'Q') {

@@ -954,2 +1035,3 @@ // CFF only supports bézier curves, so convert the quad to a bézier.

var _23 = 2 / 3;
// We're going to create a new command so we don't change the original path.

@@ -984,6 +1066,6 @@ cmd = {

} else if (cmd.type === 'C') {
dx1 = Math.round(cmd.x1 - x);
dy1 = Math.round(cmd.y1 - y);
dx2 = Math.round(cmd.x2 - cmd.x1);
dy2 = Math.round(cmd.y2 - cmd.y1);
var dx1 = Math.round(cmd.x1 - x);
var dy1 = Math.round(cmd.y1 - y);
var dx2 = Math.round(cmd.x2 - cmd.x1);
var dy2 = Math.round(cmd.y2 - cmd.y1);
dx = Math.round(cmd.x - cmd.x2);

@@ -1000,6 +1082,8 @@ dy = Math.round(cmd.y - cmd.y2);

y = Math.round(cmd.y);
} else if (cmd.type === 'Z') {
// Contours are closed automatically.
}
// Contours are closed automatically.
}
ops.push({name: 'endchar', type: 'OP', value: 14});

@@ -1018,2 +1102,3 @@ return ops;

}
return t;

@@ -1067,2 +1152,3 @@ }

var glyphNames = [];
// Skip first glyph (.notdef)

@@ -1094,3 +1180,5 @@ for (var i = 1; i < glyphs.length; i += 1) {

attrs.charset = startOffset;
attrs.encoding = 0; // We use the CFF standard encoding; proper encoding will be handled in cmap.
// We use the CFF standard encoding; proper encoding will be handled in cmap.
attrs.encoding = 0;
attrs.charStrings = attrs.charset + t.charsets.sizeOf();

@@ -1097,0 +1185,0 @@ attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf();

@@ -14,16 +14,14 @@ // The `cmap` table stores the mappings from characters to glyphs.

function parseCmapTable(data, start) {
var version, numTables, offset, platformId, encodingId, format, segCount,
endCountParser, startCountParser, idDeltaParser, idRangeOffsetParser, glyphIndexOffset,
endCount, startCount, i, c, idDelta, idRangeOffset, p, glyphIndex;
var i;
var cmap = {};
cmap.version = version = parse.getUShort(data, start);
check.argument(version === 0, 'cmap table version should be 0.');
cmap.version = parse.getUShort(data, start);
check.argument(cmap.version === 0, 'cmap table version should be 0.');
// The cmap table can contain many sub-tables, each with their own format.
// We're only interested in a "platform 3" table. This is a Windows format.
cmap.numtables = numTables = parse.getUShort(data, start + 2);
offset = -1;
for (i = 0; i < numTables; i += 1) {
platformId = parse.getUShort(data, start + 4 + (i * 8));
encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2);
cmap.numTables = parse.getUShort(data, start + 2);
var offset = -1;
for (i = 0; i < cmap.numTables; i += 1) {
var platformId = parse.getUShort(data, start + 4 + (i * 8));
var encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2);
if (platformId === 3 && (encodingId === 1 || encodingId === 0)) {

@@ -34,2 +32,3 @@ offset = parse.getULong(data, start + 4 + (i * 8) + 4);

}
if (offset === -1) {

@@ -41,10 +40,14 @@ // There is no cmap table in the font that we support, so return null.

p = new parse.Parser(data, start + offset);
cmap.format = format = p.parseUShort();
check.argument(format === 4, 'Only format 4 cmap tables are supported.');
var p = new parse.Parser(data, start + offset);
cmap.format = p.parseUShort();
check.argument(cmap.format === 4, 'Only format 4 cmap tables are supported.');
// Length in bytes of the sub-tables.
cmap.length = p.parseUShort();
cmap.language = p.parseUShort();
// segCount is stored x 2.
var segCount;
cmap.segCount = segCount = p.parseUShort() >> 1;
// Skip searchRange, entrySelector, rangeShift.

@@ -56,13 +59,14 @@ p.skip('uShort', 3);

endCountParser = new parse.Parser(data, start + offset + 14);
startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2);
idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4);
idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6);
glyphIndexOffset = start + offset + 16 + segCount * 8;
var endCountParser = new parse.Parser(data, start + offset + 14);
var startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2);
var idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4);
var idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6);
var glyphIndexOffset = start + offset + 16 + segCount * 8;
for (i = 0; i < segCount - 1; i += 1) {
endCount = endCountParser.parseUShort();
startCount = startCountParser.parseUShort();
idDelta = idDeltaParser.parseShort();
idRangeOffset = idRangeOffsetParser.parseUShort();
for (c = startCount; c <= endCount; c += 1) {
var glyphIndex;
var endCount = endCountParser.parseUShort();
var startCount = startCountParser.parseUShort();
var idDelta = idDeltaParser.parseShort();
var idRangeOffset = idRangeOffsetParser.parseUShort();
for (var c = startCount; c <= endCount; c += 1) {
if (idRangeOffset !== 0) {

@@ -72,4 +76,6 @@ // The idRangeOffset is relative to the current position in the idRangeOffset array.

glyphIndexOffset = (idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2);
// Add the value of the idRangeOffset, which will move us into the glyphIndex array.
glyphIndexOffset += idRangeOffset;
// Then add the character index of the current segment, multiplied by 2 for USHORTs.

@@ -84,5 +90,7 @@ glyphIndexOffset += (c - startCount) * 2;

}
cmap.glyphIndexMap[c] = glyphIndex;
}
}
return cmap;

@@ -110,3 +118,3 @@ }

function makeCmapTable(glyphs) {
var i, j, glyph;
var i;
var t = new table.Table('cmap', [

@@ -129,10 +137,12 @@ {name: 'version', type: 'USHORT', value: 0},

for (i = 0; i < glyphs.length; i += 1) {
glyph = glyphs[i];
for (j = 0; j < glyph.unicodes.length; j += 1) {
var glyph = glyphs[i];
for (var j = 0; j < glyph.unicodes.length; j += 1) {
addSegment(t, glyph.unicodes[j], i);
}
t.segments = t.segments.sort(function (a, b) {
t.segments = t.segments.sort(function(a, b) {
return a.start - b.start;
});
}
addTerminatorSegment(t);

@@ -147,8 +157,8 @@

// Set up parallel segment arrays.
var endCounts = [],
startCounts = [],
idDeltas = [],
idRangeOffsets = [],
glyphIds = [];
// Set up parallel segment arrays.
var endCounts = [];
var startCounts = [];
var idDeltas = [];
var idRangeOffsets = [];
var glyphIds = [];

@@ -165,2 +175,3 @@ for (i = 0; i < segCount; i += 1) {

}
t.fields = t.fields.concat(endCounts);

@@ -180,2 +191,3 @@ t.fields.push({name: 'reservedPad', type: 'USHORT', value: 0});

glyphIds.length * 2;
return t;

@@ -182,0 +194,0 @@ }

@@ -21,2 +21,3 @@ // The `glyf` table describes the glyphs in TrueType outline format.

}
v = previousValue + v;

@@ -33,2 +34,3 @@ } else {

}
return v;

@@ -39,7 +41,7 @@ }

function parseGlyph(data, start, index, font) {
var p, glyph, flag, i, j, flags,
endPointIndices, numberOfCoordinates, repeatCount, points, point, px, py,
component, moreComponents;
p = new parse.Parser(data, start);
glyph = new _glyph.Glyph({font: font, index: index});
//var p, glyph, flag, i, j, flags,
// endPointIndices, numberOfCoordinates, repeatCount, points, point, px, py,
// component, moreComponents;
var p = new parse.Parser(data, start);
var glyph = new _glyph.Glyph({font: font, index: index});
glyph.numberOfContours = p.parseShort();

@@ -50,5 +52,8 @@ glyph.xMin = p.parseShort();

glyph.yMax = p.parseShort();
var flags;
var flag;
if (glyph.numberOfContours > 0) {
var i;
// This glyph is not a composite.
endPointIndices = glyph.endPointIndices = [];
var endPointIndices = glyph.endPointIndices = [];
for (i = 0; i < glyph.numberOfContours; i += 1) {

@@ -64,3 +69,3 @@ endPointIndices.push(p.parseUShort());

numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;
var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;
flags = [];

@@ -72,4 +77,4 @@ for (i = 0; i < numberOfCoordinates; i += 1) {

if ((flag & 8) > 0) {
repeatCount = p.parseByte();
for (j = 0; j < repeatCount; j += 1) {
var repeatCount = p.parseByte();
for (var j = 0; j < repeatCount; j += 1) {
flags.push(flag);

@@ -80,6 +85,8 @@ i += 1;

}
check.argument(flags.length === numberOfCoordinates, 'Bad flags.');
if (endPointIndices.length > 0) {
points = [];
var points = [];
var point;
// X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.

@@ -94,3 +101,4 @@ if (numberOfCoordinates > 0) {

}
px = 0;
var px = 0;
for (i = 0; i < numberOfCoordinates; i += 1) {

@@ -103,3 +111,3 @@ flag = flags[i];

py = 0;
var py = 0;
for (i = 0; i < numberOfCoordinates; i += 1) {

@@ -112,2 +120,3 @@ flag = flags[i];

}
glyph.points = points;

@@ -123,14 +132,14 @@ } else {

glyph.components = [];
moreComponents = true;
var moreComponents = true;
while (moreComponents) {
flags = p.parseUShort();
component = {
var component = {
glyphIndex: p.parseUShort(),
xScale: 1,
scale01: 0,
scale10: 0,
yScale: 1,
dx: 0,
dy: 0
};
xScale: 1,
scale01: 0,
scale10: 0,
yScale: 1,
dx: 0,
dy: 0
};
if ((flags & 1) > 0) {

@@ -145,2 +154,3 @@ // The arguments are words

}
if ((flags & 8) > 0) {

@@ -165,2 +175,3 @@ // We have a scale

}
return glyph;

@@ -171,7 +182,6 @@ }

function transformPoints(points, transform) {
var newPoints, i, pt, newPt;
newPoints = [];
for (i = 0; i < points.length; i += 1) {
pt = points[i];
newPt = {
var newPoints = [];
for (var i = 0; i < points.length; i += 1) {
var pt = points[i];
var newPt = {
x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx,

@@ -184,12 +194,11 @@ y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy,

}
return newPoints;
}
function getContours(points) {
var contours, currentContour, i, pt;
contours = [];
currentContour = [];
for (i = 0; i < points.length; i += 1) {
pt = points[i];
var contours = [];
var currentContour = [];
for (var i = 0; i < points.length; i += 1) {
var pt = points[i];
currentContour.push(pt);

@@ -201,2 +210,3 @@ if (pt.lastPointOfContour) {

}
check.argument(currentContour.length === 0, 'There are still points left in the current contour.');

@@ -208,13 +218,14 @@ return contours;

function getPath(points) {
var p, contours, i, realFirstPoint, j, contour, pt, firstPt,
prevPt, midPt, curvePt, lastPt;
p = new path.Path();
var p = new path.Path();
if (!points) {
return p;
}
contours = getContours(points);
for (i = 0; i < contours.length; i += 1) {
contour = contours[i];
firstPt = contour[0];
lastPt = contour[contour.length - 1];
var contours = getContours(points);
for (var i = 0; i < contours.length; i += 1) {
var contour = contours[i];
var firstPt = contour[0];
var lastPt = contour[contour.length - 1];
var curvePt;
var realFirstPoint;
if (firstPt.onCurve) {

@@ -234,2 +245,3 @@ curvePt = null;

}
curvePt = firstPt;

@@ -239,7 +251,8 @@ // The first point is synthesized, so don't skip the real first point.

}
p.moveTo(firstPt.x, firstPt.y);
for (j = realFirstPoint ? 1 : 0; j < contour.length; j += 1) {
pt = contour[j];
prevPt = j === 0 ? firstPt : contour[j - 1];
for (var j = realFirstPoint ? 1 : 0; j < contour.length; j += 1) {
var pt = contour[j];
var prevPt = j === 0 ? firstPt : contour[j - 1];
if (prevPt.onCurve && pt.onCurve) {

@@ -251,3 +264,3 @@ // This is a straight line.

} else if (!prevPt.onCurve && !pt.onCurve) {
midPt = { x: (prevPt.x + pt.x) / 2, y: (prevPt.y + pt.y) / 2 };
var midPt = { x: (prevPt.x + pt.x) / 2, y: (prevPt.y + pt.y) / 2 };
p.quadraticCurveTo(prevPt.x, prevPt.y, midPt.x, midPt.y);

@@ -263,2 +276,3 @@ curvePt = pt;

}
if (firstPt !== lastPt) {

@@ -273,2 +287,3 @@ // Connect the last and first points

}
p.closePath();

@@ -280,9 +295,8 @@ return p;

function parseGlyfTable(data, start, loca, font) {
var glyphs, i, j, offset, nextOffset, glyph,
component, componentGlyph, transformedPoints;
glyphs = [];
var glyphs = [];
var i;
// The last element of the loca table is invalid.
for (i = 0; i < loca.length - 1; i += 1) {
offset = loca[i];
nextOffset = loca[i + 1];
var offset = loca[i];
var nextOffset = loca[i + 1];
if (offset !== nextOffset) {

@@ -296,9 +310,9 @@ glyphs.push(parseGlyph(data, start + offset, i, font));

for (i = 0; i < glyphs.length; i += 1) {
glyph = glyphs[i];
var glyph = glyphs[i];
if (glyph.isComposite) {
for (j = 0; j < glyph.components.length; j += 1) {
component = glyph.components[j];
componentGlyph = glyphs[component.glyphIndex];
for (var j = 0; j < glyph.components.length; j += 1) {
var component = glyph.components[j];
var componentGlyph = glyphs[component.glyphIndex];
if (componentGlyph.points) {
transformedPoints = transformPoints(componentGlyph.points, component);
var transformedPoints = transformPoints(componentGlyph.points, component);
glyph.points = glyph.points.concat(transformedPoints);

@@ -308,4 +322,6 @@ }

}
glyph.path = getPath(glyph.points);
}
return glyphs;

@@ -312,0 +328,0 @@ }

@@ -12,8 +12,9 @@ // The `GPOS` table contains kerning pairs, among other things.

function parseTaggedListTable(data, start) {
var p = new parse.Parser(data, start),
n = p.parseUShort(),
list = [];
var p = new parse.Parser(data, start);
var n = p.parseUShort();
var list = [];
for (var i = 0; i < n; i++) {
list[p.parseTag()] = { offset: p.parseUShort() };
}
return list;

@@ -26,5 +27,5 @@ }

function parseCoverageTable(data, start) {
var p = new parse.Parser(data, start),
format = p.parseUShort(),
count = p.parseUShort();
var p = new parse.Parser(data, start);
var format = p.parseUShort();
var count = p.parseUShort();
if (format === 1) {

@@ -34,11 +35,12 @@ return p.parseUShortList(count);

else if (format === 2) {
var i, begin, end, index, coverage = [];
var coverage = [];
for (; count--;) {
begin = p.parseUShort();
end = p.parseUShort();
index = p.parseUShort();
for (i = begin; i <= end; i++) {
var begin = p.parseUShort();
var end = p.parseUShort();
var index = p.parseUShort();
for (var i = begin; i <= end; i++) {
coverage[index++] = i;
}
}
return coverage;

@@ -51,9 +53,9 @@ }

function parseClassDefTable(data, start) {
var p = new parse.Parser(data, start),
format = p.parseUShort();
var p = new parse.Parser(data, start);
var format = p.parseUShort();
if (format === 1) {
// Format 1 specifies a range of consecutive glyph indices, one class per glyph ID.
var startGlyph = p.parseUShort(),
glyphCount = p.parseUShort(),
classes = p.parseUShortList(glyphCount);
var startGlyph = p.parseUShort();
var glyphCount = p.parseUShort();
var classes = p.parseUShortList(glyphCount);
return function(glyphID) {

@@ -65,6 +67,6 @@ return classes[glyphID - startGlyph] || 0;

// Format 2 defines multiple groups of glyph indices that belong to the same class.
var rangeCount = p.parseUShort(),
startGlyphs = [],
endGlyphs = [],
classValues = [];
var rangeCount = p.parseUShort();
var startGlyphs = [];
var endGlyphs = [];
var classValues = [];
for (var i = 0; i < rangeCount; i++) {

@@ -75,8 +77,8 @@ startGlyphs[i] = p.parseUShort();

}
return function(glyphID) {
var l, c, r;
l = 0;
r = startGlyphs.length - 1;
var l = 0;
var r = startGlyphs.length - 1;
while (l < r) {
c = (l + r + 1) >> 1;
var c = (l + r + 1) >> 1;
if (glyphID < startGlyphs[c]) {

@@ -88,5 +90,7 @@ r = c - 1;

}
if (startGlyphs[l] <= glyphID && glyphID <= endGlyphs[l]) {
return classValues[l] || 0;
}
return 0;

@@ -101,24 +105,23 @@ };

var p = new parse.Parser(data, start);
var format, coverageOffset, coverage, valueFormat1, valueFormat2,
sharedPairSets, firstGlyph, secondGlyph, value1, value2;
// This part is common to format 1 and format 2 subtables
format = p.parseUShort();
coverageOffset = p.parseUShort();
coverage = parseCoverageTable(data, start + coverageOffset);
var format = p.parseUShort();
var coverageOffset = p.parseUShort();
var coverage = parseCoverageTable(data, start + coverageOffset);
// valueFormat 4: XAdvance only, 1: XPlacement only, 0: no ValueRecord for second glyph
// Only valueFormat1=4 and valueFormat2=0 is supported.
valueFormat1 = p.parseUShort();
valueFormat2 = p.parseUShort();
var valueFormat1 = p.parseUShort();
var valueFormat2 = p.parseUShort();
var value1;
var value2;
if (valueFormat1 !== 4 || valueFormat2 !== 0) return;
sharedPairSets = {};
var sharedPairSets = {};
if (format === 1) {
// Pair Positioning Adjustment: Format 1
var pairSetCount, pairSetOffsets, pairSetOffset, sharedPairSet, pairValueCount, pairSet;
pairSetCount = p.parseUShort();
pairSet = [];
var pairSetCount = p.parseUShort();
var pairSet = [];
// Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index
pairSetOffsets = p.parseOffset16List(pairSetCount);
for (firstGlyph = 0; firstGlyph < pairSetCount; firstGlyph++) {
pairSetOffset = pairSetOffsets[firstGlyph];
sharedPairSet = sharedPairSets[pairSetOffset];
var pairSetOffsets = p.parseOffset16List(pairSetCount);
for (var firstGlyph = 0; firstGlyph < pairSetCount; firstGlyph++) {
var pairSetOffset = pairSetOffsets[firstGlyph];
var sharedPairSet = sharedPairSets[pairSetOffset];
if (!sharedPairSet) {

@@ -128,5 +131,5 @@ // Parse a pairset table in a pair adjustment subtable format 1

p.relativeOffset = pairSetOffset;
pairValueCount = p.parseUShort();
var pairValueCount = p.parseUShort();
for (; pairValueCount--;) {
secondGlyph = p.parseUShort();
var secondGlyph = p.parseUShort();
if (valueFormat1) value1 = p.parseShort();

@@ -139,4 +142,6 @@ if (valueFormat2) value2 = p.parseShort();

}
pairSet[coverage[firstGlyph]] = sharedPairSet;
}
return function(leftGlyph, rightGlyph) {

@@ -149,16 +154,14 @@ var pairs = pairSet[leftGlyph];

// Pair Positioning Adjustment: Format 2
var classDef1Offset, classDef2Offset, class1Count, class2Count, i, j,
getClass1, getClass2, kerningMatrix, kerningRow, covered;
classDef1Offset = p.parseUShort();
classDef2Offset = p.parseUShort();
class1Count = p.parseUShort();
class2Count = p.parseUShort();
getClass1 = parseClassDefTable(data, start+classDef1Offset);
getClass2 = parseClassDefTable(data, start+classDef2Offset);
var classDef1Offset = p.parseUShort();
var classDef2Offset = p.parseUShort();
var class1Count = p.parseUShort();
var class2Count = p.parseUShort();
var getClass1 = parseClassDefTable(data, start + classDef1Offset);
var getClass2 = parseClassDefTable(data, start + classDef2Offset);
// Parse kerning values by class pair.
kerningMatrix = [];
for (i = 0; i < class1Count; i++) {
kerningRow = kerningMatrix[i] = [];
for (j = 0; j < class2Count; j++) {
var kerningMatrix = [];
for (var i = 0; i < class1Count; i++) {
var kerningRow = kerningMatrix[i] = [];
for (var j = 0; j < class2Count; j++) {
if (valueFormat1) value1 = p.parseShort();

@@ -173,4 +176,4 @@ if (valueFormat2) value2 = p.parseShort();

// Convert coverage list to a hash
covered = {};
for(i = 0; i < coverage.length; i++) covered[coverage[i]] = 1;
var covered = {};
for (i = 0; i < coverage.length; i++) covered[coverage[i]] = 1;

@@ -180,5 +183,5 @@ // Get the kerning value for a specific glyph pair.

if (!covered[leftGlyph]) return;
var class1 = getClass1(leftGlyph),
class2 = getClass2(rightGlyph),
kerningRow = kerningMatrix[class1];
var class1 = getClass1(leftGlyph);
var class2 = getClass2(rightGlyph);
var kerningRow = kerningMatrix[class1];

@@ -195,9 +198,8 @@ if (kerningRow) {

var p = new parse.Parser(data, start);
var table, lookupType, lookupFlag, useMarkFilteringSet, subTableCount, subTableOffsets, subtables, i;
lookupType = p.parseUShort();
lookupFlag = p.parseUShort();
useMarkFilteringSet = lookupFlag & 0x10;
subTableCount = p.parseUShort();
subTableOffsets = p.parseOffset16List(subTableCount);
table = {
var lookupType = p.parseUShort();
var lookupFlag = p.parseUShort();
var useMarkFilteringSet = lookupFlag & 0x10;
var subTableCount = p.parseUShort();
var subTableOffsets = p.parseOffset16List(subTableCount);
var table = {
lookupType: lookupType,

@@ -209,4 +211,4 @@ lookupFlag: lookupFlag,

if (lookupType === 2) {
subtables = [];
for (i = 0; i < subTableCount; i++) {
var subtables = [];
for (var i = 0; i < subTableCount; i++) {
subtables.push(parsePairPosSubTable(data, start + subTableOffsets[i]));

@@ -220,5 +222,7 @@ }

}
return 0;
};
}
return table;

@@ -230,22 +234,19 @@ }

function parseGposTable(data, start, font) {
var p, tableVersion, lookupListOffset, scriptList, i, featureList, lookupCount,
lookupTableOffsets, lookupListAbsoluteOffset, table;
p = new parse.Parser(data, start);
tableVersion = p.parseFixed();
var p = new parse.Parser(data, start);
var tableVersion = p.parseFixed();
check.argument(tableVersion === 1, 'Unsupported GPOS table version.');
// ScriptList and FeatureList - ignored for now
scriptList = parseTaggedListTable(data, start+p.parseUShort());
parseTaggedListTable(data, start + p.parseUShort());
// 'kern' is the feature we are looking for.
featureList = parseTaggedListTable(data, start+p.parseUShort());
parseTaggedListTable(data, start + p.parseUShort());
// LookupList
lookupListOffset = p.parseUShort();
var lookupListOffset = p.parseUShort();
p.relativeOffset = lookupListOffset;
lookupCount = p.parseUShort();
lookupTableOffsets = p.parseOffset16List(lookupCount);
lookupListAbsoluteOffset = start + lookupListOffset;
for (i = 0; i < lookupCount; i++) {
table = parseLookupTable(data, lookupListAbsoluteOffset + lookupTableOffsets[i]);
var lookupCount = p.parseUShort();
var lookupTableOffsets = p.parseOffset16List(lookupCount);
var lookupListAbsoluteOffset = start + lookupListOffset;
for (var i = 0; i < lookupCount; i++) {
var table = parseLookupTable(data, lookupListAbsoluteOffset + lookupTableOffsets[i]);
if (table.lookupType === 2 && !font.getGposKerningValue) font.getGposKerningValue = table.getKerningValue;

@@ -252,0 +253,0 @@ }

@@ -12,4 +12,4 @@ // The `head` table contains global information about the font.

function parseHeadTable(data, start) {
var head = {},
p = new parse.Parser(data, start);
var head = {};
var p = new parse.Parser(data, start);
head.version = p.parseVersion();

@@ -16,0 +16,0 @@ head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000;

@@ -11,4 +11,4 @@ // The `hhea` table contains information for horizontal layout.

function parseHheaTable(data, start) {
var hhea = {},
p = new parse.Parser(data, start);
var hhea = {};
var p = new parse.Parser(data, start);
hhea.version = p.parseVersion();

@@ -15,0 +15,0 @@ hhea.ascender = p.parseShort();

@@ -12,5 +12,6 @@ // The `hmtx` table contains the horizontal metrics for all glyphs.

function parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) {
var p, i, glyph, advanceWidth, leftSideBearing;
p = new parse.Parser(data, start);
for (i = 0; i < numGlyphs; i += 1) {
var advanceWidth;
var leftSideBearing;
var p = new parse.Parser(data, start);
for (var i = 0; i < numGlyphs; i += 1) {
// If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs.

@@ -21,3 +22,4 @@ if (i < numMetrics) {

}
glyph = glyphs[i];
var glyph = glyphs[i];
glyph.advanceWidth = advanceWidth;

@@ -37,2 +39,3 @@ glyph.leftSideBearing = leftSideBearing;

}
return t;

@@ -43,4 +46,1 @@ }

exports.make = makeHmtxTable;

@@ -12,23 +12,22 @@ // The `kern` table contains kerning pairs.

function parseKernTable(data, start) {
var pairs, p, tableVersion, subTableVersion, nPairs,
i, leftIndex, rightIndex, value;
pairs = {};
p = new parse.Parser(data, start);
tableVersion = p.parseUShort();
var pairs = {};
var p = new parse.Parser(data, start);
var tableVersion = p.parseUShort();
check.argument(tableVersion === 0, 'Unsupported kern table version.');
// Skip nTables.
p.skip('uShort', 1);
subTableVersion = p.parseUShort();
var subTableVersion = p.parseUShort();
check.argument(subTableVersion === 0, 'Unsupported kern sub-table version.');
// Skip subTableLength, subTableCoverage
p.skip('uShort', 2);
nPairs = p.parseUShort();
var nPairs = p.parseUShort();
// Skip searchRange, entrySelector, rangeShift.
p.skip('uShort', 3);
for (i = 0; i < nPairs; i += 1) {
leftIndex = p.parseUShort();
rightIndex = p.parseUShort();
value = p.parseShort();
for (var i = 0; i < nPairs; i += 1) {
var leftIndex = p.parseUShort();
var rightIndex = p.parseUShort();
var value = p.parseShort();
pairs[leftIndex + ',' + rightIndex] = value;
}
return pairs;

@@ -35,0 +34,0 @@ }

@@ -15,10 +15,9 @@ // The `loca` table stores the offsets to the locations of the glyphs in the font.

function parseLocaTable(data, start, numGlyphs, shortVersion) {
var p, parseFn, glyphOffsets, glyphOffset, i;
p = new parse.Parser(data, start);
parseFn = shortVersion ? p.parseUShort : p.parseULong;
var p = new parse.Parser(data, start);
var parseFn = shortVersion ? p.parseUShort : p.parseULong;
// There is an extra entry after the last index element to compute the length of the last glyph.
// That's why we use numGlyphs + 1.
glyphOffsets = [];
for (i = 0; i < numGlyphs + 1; i += 1) {
glyphOffset = parseFn.call(p);
var glyphOffsets = [];
for (var i = 0; i < numGlyphs + 1; i += 1) {
var glyphOffset = parseFn.call(p);
if (shortVersion) {

@@ -28,4 +27,6 @@ // The short table version stores the actual offset divided by 2.

}
glyphOffsets.push(glyphOffset);
}
return glyphOffsets;

@@ -32,0 +33,0 @@ }

@@ -12,4 +12,4 @@ // The `maxp` table establishes the memory requirements for the font.

function parseMaxpTable(data, start) {
var maxp = {},
p = new parse.Parser(data, start);
var maxp = {};
var p = new parse.Parser(data, start);
maxp.version = p.parseVersion();

@@ -32,2 +32,3 @@ maxp.numGlyphs = p.parseUShort();

}
return maxp;

@@ -34,0 +35,0 @@ }

@@ -41,18 +41,16 @@ // The `name` naming table.

function parseNameTable(data, start) {
var name = {},
p = new parse.Parser(data, start);
var name = {};
var p = new parse.Parser(data, start);
name.format = p.parseUShort();
var count = p.parseUShort(),
stringOffset = p.offset + p.parseUShort();
var platformID, encodingID, languageID, nameID, property, byteLength,
offset, str, i, j, codePoints;
var count = p.parseUShort();
var stringOffset = p.offset + p.parseUShort();
var unknownCount = 0;
for(i = 0; i < count; i++) {
platformID = p.parseUShort();
encodingID = p.parseUShort();
languageID = p.parseUShort();
nameID = p.parseUShort();
property = nameTableNames[nameID];
byteLength = p.parseUShort();
offset = p.parseUShort();
for (var i = 0; i < count; i++) {
var platformID = p.parseUShort();
var encodingID = p.parseUShort();
var languageID = p.parseUShort();
var nameID = p.parseUShort();
var property = nameTableNames[nameID];
var byteLength = p.parseUShort();
var offset = p.parseUShort();
// platformID - encodingID - languageID standard combinations :

@@ -62,8 +60,9 @@ // 1 - 0 - 0 : Macintosh, Roman, English

if (platformID === 3 && encodingID === 1 && languageID === 0x409) {
codePoints = [];
var length = byteLength/2;
for(j = 0; j < length; j++, offset += 2) {
codePoints[j] = parse.getShort(data, stringOffset+offset);
var codePoints = [];
var length = byteLength / 2;
for (var j = 0; j < length; j++, offset += 2) {
codePoints[j] = parse.getShort(data, stringOffset + offset);
}
str = String.fromCharCode.apply(null, codePoints);
var str = String.fromCharCode.apply(null, codePoints);
if (property) {

@@ -74,3 +73,3 @@ name[property] = str;

unknownCount++;
name['unknown'+unknownCount] = str;
name['unknown' + unknownCount] = str;
}

@@ -80,5 +79,7 @@ }

}
if (name.format === 1) {
name.langTagCount = p.parseUShort();
}
return name;

@@ -117,3 +118,2 @@ }

function makeNameTable(options) {
var i, s;
var t = new table.Table('name', [

@@ -127,2 +127,4 @@ {name: 'format', type: 'USHORT', value: 0},

var offset = 0;
var i;
var s;
// Add Macintosh records first

@@ -148,5 +150,7 @@ for (i = 0; i < nameTableNames.length; i += 1) {

}
for (i = 0; i < t.strings.length; i += 1) {
t.fields.push({name: 'string_' + i, type: 'LITERAL', value: t.strings[i]});
}
return t;

@@ -153,0 +157,0 @@ }

@@ -142,2 +142,3 @@ // The `OS/2` table contains metrics required in OpenType fonts.

}
return -1;

@@ -148,4 +149,4 @@ }

function parseOS2Table(data, start) {
var os2 = {},
p = new parse.Parser(data, start);
var os2 = {};
var p = new parse.Parser(data, start);
os2.version = p.parseUShort();

@@ -171,2 +172,3 @@ os2.xAvgCharWidth = p.parseShort();

}
os2.ulUnicodeRange1 = p.parseULong();

@@ -189,2 +191,3 @@ os2.ulUnicodeRange2 = p.parseULong();

}
if (os2.version >= 2) {

@@ -197,2 +200,3 @@ os2.sxHeight = p.parseShort();

}
return os2;

@@ -199,0 +203,0 @@ }

@@ -12,5 +12,5 @@ // The `post` table stores additional PostScript information, such as glyph names.

function parsePostTable(data, start) {
var post = {},
p = new parse.Parser(data, start),
i, nameLength;
var post = {};
var p = new parse.Parser(data, start);
var i;
post.version = p.parseVersion();

@@ -35,9 +35,11 @@ post.italicAngle = p.parseFixed();

}
post.names = [];
for (i = 0; i < post.numberOfGlyphs; i++) {
if (post.glyphNameIndex[i] >= encoding.standardNames.length) {
nameLength = p.parseChar();
var nameLength = p.parseChar();
post.names.push(p.parseString(nameLength));
}
}
break;

@@ -50,2 +52,3 @@ case 2.5:

}
break;

@@ -52,0 +55,0 @@ }

@@ -30,2 +30,3 @@ // The `sfnt` wrapper provides organization for the tables in the font.

}
var sum = 0;

@@ -38,2 +39,3 @@ for (var i = 0; i < bytes.length; i += 4) {

}
sum %= Math.pow(2, 32);

@@ -92,3 +94,3 @@ return sum;

// Table records need to be sorted alphabetically.
recordFields.sort(function (r1, r2) {
recordFields.sort(function(r1, r2) {
if (r1.value.tag > r2.value.tag) {

@@ -117,2 +119,3 @@ return 1;

}
return notFoundMetrics;

@@ -126,2 +129,3 @@ }

}
return sum / vs.length;

@@ -152,5 +156,7 @@ }

}
if (lastCharIndex < unicode) {
lastCharIndex = unicode;
}
var position = os2.getUnicodeRange(unicode);

@@ -179,2 +185,3 @@ if (position < 32) {

}
var globals = {

@@ -191,4 +198,4 @@ xMin: Math.min.apply(null, xMins),

};
globals.ascender = globals.yMax;
globals.descender = globals.yMin;
globals.ascender = font.ascender !== undefined ? font.ascender : globals.yMax;
globals.descender = font.descender !== undefined ? font.descender : globals.yMin;

@@ -239,3 +246,2 @@ var headTable = head.make({

var hmtxTable = hmtx.make(font.glyphs);

@@ -290,2 +296,3 @@ var cmapTable = cmap.make(font.glyphs);

}
if (!checkSumAdjusted) {

@@ -292,0 +299,0 @@ throw new Error('Could not find head table with checkSum to adjust.');

@@ -19,3 +19,3 @@ // Data types used in the OpenType font file.

function constant(v) {
return function () {
return function() {
return v;

@@ -28,3 +28,3 @@ };

// Convert an 8-bit unsigned integer to a list of 1 byte.
encode.BYTE = function (v) {
encode.BYTE = function(v) {
check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');

@@ -37,3 +37,3 @@ return [v];

// Convert a 8-bit signed integer to a list of 1 byte.
encode.CHAR = function (v) {
encode.CHAR = function(v) {
return [v.charCodeAt(0)];

@@ -45,3 +45,3 @@ };

// Convert an ASCII string to a list of bytes.
encode.CHARARRAY = function (v) {
encode.CHARARRAY = function(v) {
var b = [];

@@ -51,6 +51,7 @@ for (var i = 0; i < v.length; i += 1) {

}
return b;
};
sizeOf.CHARARRAY = function (v) {
sizeOf.CHARARRAY = function(v) {
return v.length;

@@ -60,3 +61,3 @@ };

// Convert a 16-bit unsigned integer to a list of 2 bytes.
encode.USHORT = function (v) {
encode.USHORT = function(v) {
return [(v >> 8) & 0xFF, v & 0xFF];

@@ -68,7 +69,8 @@ };

// Convert a 16-bit signed integer to a list of 2 bytes.
encode.SHORT = function (v) {
encode.SHORT = function(v) {
// Two's complement
if (v >= LIMIT16){
v = - ( 2 * LIMIT16 - v);
if (v >= LIMIT16) {
v = -(2 * LIMIT16 - v);
}
return [(v >> 8) & 0xFF, v & 0xFF];

@@ -80,3 +82,3 @@ };

// Convert a 24-bit unsigned integer to a list of 3 bytes.
encode.UINT24 = function (v) {
encode.UINT24 = function(v) {
return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];

@@ -88,3 +90,3 @@ };

// Convert a 32-bit unsigned integer to a list of 4 bytes.
encode.ULONG = function (v) {
encode.ULONG = function(v) {
return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];

@@ -96,7 +98,8 @@ };

// Convert a 32-bit unsigned integer to a list of 4 bytes.
encode.LONG = function (v) {
// Two's complement
if (v >= LIMIT32){
v = - ( 2 * LIMIT32 - v);
encode.LONG = function(v) {
// Two's complement
if (v >= LIMIT32) {
v = -(2 * LIMIT32 - v);
}
return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];

@@ -116,5 +119,4 @@ };

// FIXME Implement LONGDATETIME
encode.LONGDATETIME = function () {
encode.LONGDATETIME = function() {
return [0, 0, 0, 0, 0, 0, 0, 0];

@@ -126,3 +128,3 @@ };

// Convert a 4-char tag to a list of 4 bytes.
encode.TAG = function (v) {
encode.TAG = function(v) {
check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');

@@ -152,6 +154,6 @@ return [v.charCodeAt(0),

// Convert a numeric operand or charstring number to a variable-size list of bytes.
encode.NUMBER = function (v) {
encode.NUMBER = function(v) {
if (v >= -107 && v <= 107) {
return [v + 139];
} else if (v >= 108 && v <= 1131 ) {
} else if (v >= 108 && v <= 1131) {
v = v - 108;

@@ -169,3 +171,3 @@ return [(v >> 8) + 247, v & 0xFF];

sizeOf.NUMBER = function (v) {
sizeOf.NUMBER = function(v) {
return encode.NUMBER(v).length;

@@ -176,3 +178,3 @@ };

// This ensures we always use three bytes, but is not the most compact format.
encode.NUMBER16 = function (v) {
encode.NUMBER16 = function(v) {
return [28, (v >> 8) & 0xFF, v & 0xFF];

@@ -186,3 +188,3 @@ };

// at the expense of wasting a few bytes for smaller numbers.
encode.NUMBER32 = function (v) {
encode.NUMBER32 = function(v) {
return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];

@@ -200,3 +202,3 @@ };

// Convert a ASCII string to a list of UTF16 bytes.
encode.UTF16 = function (v) {
encode.UTF16 = function(v) {
var b = [];

@@ -207,6 +209,7 @@ for (var i = 0; i < v.length; i += 1) {

}
return b;
};
sizeOf.UTF16 = function (v) {
sizeOf.UTF16 = function(v) {
return v.length * 2;

@@ -217,14 +220,15 @@ };

// The values should be objects containing name / type / value.
encode.INDEX = function (l) {
var offSize, offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
dataSize, i, v;
encode.INDEX = function(l) {
var i;
//var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
// dataSize, i, v;
// Because we have to know which data type to use to encode the offsets,
// we have to go through the values twice: once to encode the data and
// calculate the offets, then again to encode the offsets using the fitting data type.
offset = 1; // First offset is always 1.
offsets = [offset];
data = [];
dataSize = 0;
var offset = 1; // First offset is always 1.
var offsets = [offset];
var data = [];
var dataSize = 0;
for (i = 0; i < l.length; i += 1) {
v = encode.OBJECT(l[i]);
var v = encode.OBJECT(l[i]);
Array.prototype.push.apply(data, v);

@@ -240,9 +244,10 @@ dataSize += v.length;

encodedOffsets = [];
offSize = (1 + Math.floor(Math.log(dataSize)/Math.log(2)) / 8) | 0;
offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];
var encodedOffsets = [];
var offSize = (1 + Math.floor(Math.log(dataSize) / Math.log(2)) / 8) | 0;
var offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];
for (i = 0; i < offsets.length; i += 1) {
encodedOffset = offsetEncoder(offsets[i]);
var encodedOffset = offsetEncoder(offsets[i]);
Array.prototype.push.apply(encodedOffsets, encodedOffset);
}
return Array.prototype.concat(encode.Card16(l.length),

@@ -254,3 +259,3 @@ encode.OffSize(offSize),

sizeOf.INDEX = function (v) {
sizeOf.INDEX = function(v) {
return encode.INDEX(v).length;

@@ -262,6 +267,6 @@ };

// The values should be objects containing name / type / value.
encode.DICT = function (m) {
var d = [],
keys = Object.keys(m),
length = keys.length;
encode.DICT = function(m) {
var d = [];
var keys = Object.keys(m);
var length = keys.length;

@@ -280,7 +285,7 @@ for (var i = 0; i < length; i += 1) {

sizeOf.DICT = function (m) {
sizeOf.DICT = function(m) {
return encode.DICT(m).length;
};
encode.OPERATOR = function (v) {
encode.OPERATOR = function(v) {
if (v < 1200) {

@@ -293,7 +298,6 @@ return [v];

encode.OPERAND = function (v, type) {
var d, i;
d = [];
encode.OPERAND = function(v, type) {
var d = [];
if (Array.isArray(type)) {
for (i = 0; i < type.length; i += 1) {
for (var i = 0; i < type.length; i += 1) {
check.argument(v.length === type.length, 'Not enough arguments given for type' + type);

@@ -314,2 +318,3 @@ d = d.concat(encode.OPERAND(v[i], type[i]));

}
return d;

@@ -324,19 +329,17 @@ };

// Convert a list of CharString operations to bytes.
encode.CHARSTRING = function (ops) {
if ( wmm && wmm.has( ops ) ) {
return wmm.get( ops );
encode.CHARSTRING = function(ops) {
if (wmm && wmm.has(ops)) {
return wmm.get(ops);
}
var d = [],
length = ops.length,
op,
i;
var d = [];
var length = ops.length;
for (i = 0; i < length; i += 1) {
op = ops[i];
d = d.concat( encode[op.type](op.value) );
for (var i = 0; i < length; i += 1) {
var op = ops[i];
d = d.concat(encode[op.type](op.value));
}
if ( wmm ) {
wmm.set( ops, d );
if (wmm) {
wmm.set(ops, d);
}

@@ -347,3 +350,3 @@

sizeOf.CHARSTRING = function (ops) {
sizeOf.CHARSTRING = function(ops) {
return encode.CHARSTRING(ops).length;

@@ -355,3 +358,3 @@ };

// Convert an object containing name / type / value to bytes.
encode.OBJECT = function (v) {
encode.OBJECT = function(v) {
var encodingFunction = encode[v.type];

@@ -365,8 +368,7 @@ check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);

// The table itself has the field values set as attributes.
encode.TABLE = function (table) {
var d = [],
length = table.fields.length,
i;
encode.TABLE = function(table) {
var d = [];
var length = table.fields.length;
for (i = 0; i < length; i += 1) {
for (var i = 0; i < length; i += 1) {
var field = table.fields[i];

@@ -379,5 +381,7 @@ var encodingFunction = encode[field.type];

}
var bytes = encodingFunction(value);
d = d.concat(bytes);
}
return d;

@@ -387,13 +391,12 @@ };

// Merge in a list of bytes.
encode.LITERAL = function (v) {
encode.LITERAL = function(v) {
return v;
};
sizeOf.LITERAL = function (v) {
sizeOf.LITERAL = function(v) {
return v.length;
};
exports.decode = decode;
exports.encode = encode;
exports.sizeOf = sizeOf;

Sorry, the diff of this file is not supported yet

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 too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc