|
|
@ -43,38 +43,39 @@ var Fonts = { |
|
|
|
this._active = this[aName]; |
|
|
|
this._active = this[aName]; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
chars2Unicode: function(chars) { |
|
|
|
charsToUnicode: function fonts_chars2Unicode(chars) { |
|
|
|
var active = this._active; |
|
|
|
var active = this._active; |
|
|
|
if (!active) |
|
|
|
if (!active) |
|
|
|
return chars; |
|
|
|
return chars; |
|
|
|
|
|
|
|
|
|
|
|
// if we translated this string before, just grab it from the cache
|
|
|
|
// if we translated this string before, just grab it from the cache
|
|
|
|
var ret = active.cache[chars]; |
|
|
|
var str = active.cache[chars] || ""; |
|
|
|
if (ret) |
|
|
|
if (str) |
|
|
|
return ret; |
|
|
|
return str; |
|
|
|
|
|
|
|
|
|
|
|
// translate the string using the font's encoding
|
|
|
|
// translate the string using the font's encoding
|
|
|
|
var encoding = active.properties.encoding; |
|
|
|
var encoding = active.properties.encoding; |
|
|
|
if (!encoding) |
|
|
|
if (!encoding) |
|
|
|
return chars; |
|
|
|
return chars; |
|
|
|
|
|
|
|
|
|
|
|
var ret = ""; |
|
|
|
|
|
|
|
for (var i = 0; i < chars.length; ++i) { |
|
|
|
for (var i = 0; i < chars.length; ++i) { |
|
|
|
var ch = chars.charCodeAt(i); |
|
|
|
var charcode = chars.charCodeAt(i); |
|
|
|
var uc = encoding[ch]; |
|
|
|
var unicode = encoding[charcode]; |
|
|
|
if (uc instanceof Name) // we didn't convert the glyph yet
|
|
|
|
|
|
|
|
uc = encoding[ch] = GlyphsUnicode[uc.name]; |
|
|
|
// Check if the glyph has already been converted
|
|
|
|
if (uc > 0xffff) { // handle surrogate pairs
|
|
|
|
if (unicode instanceof Name) |
|
|
|
ret += String.fromCharCode(uc & 0xffff); |
|
|
|
unicode = encoding[unicode] = GlyphsUnicode[unicode.name]; |
|
|
|
uc >>= 16; |
|
|
|
|
|
|
|
|
|
|
|
// Handle surrogate pairs
|
|
|
|
|
|
|
|
if (unicode > 0xFFFF) { |
|
|
|
|
|
|
|
str += String.fromCharCode(unicode & 0xFFFF); |
|
|
|
|
|
|
|
unicode >>= 16; |
|
|
|
} |
|
|
|
} |
|
|
|
ret += String.fromCharCode(uc); |
|
|
|
str += String.fromCharCode(unicode); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// enter the translated string into the cache
|
|
|
|
// Enter the translated string into the cache
|
|
|
|
active.cache[chars] = ret; |
|
|
|
return active.cache[chars] = str; |
|
|
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -99,6 +100,8 @@ var Font = (function () { |
|
|
|
fontCount++; |
|
|
|
fontCount++; |
|
|
|
fontName = aName; |
|
|
|
fontName = aName; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If the font is to be ignored, register it like an already loaded font
|
|
|
|
|
|
|
|
// to avoid the cost of waiting for it be be loaded by the platform.
|
|
|
|
if (aProperties.ignore || kDisableFonts) { |
|
|
|
if (aProperties.ignore || kDisableFonts) { |
|
|
|
Fonts[aName] = { |
|
|
|
Fonts[aName] = { |
|
|
|
data: aFile, |
|
|
|
data: aFile, |
|
|
@ -168,31 +171,12 @@ var Font = (function () { |
|
|
|
|
|
|
|
|
|
|
|
bind: function font_bind() { |
|
|
|
bind: function font_bind() { |
|
|
|
var data = this.font; |
|
|
|
var data = this.font; |
|
|
|
|
|
|
|
|
|
|
|
// Get the base64 encoding of the binary font data
|
|
|
|
|
|
|
|
var str = ""; |
|
|
|
|
|
|
|
var length = data.length; |
|
|
|
|
|
|
|
for (var i = 0; i < length; ++i) |
|
|
|
|
|
|
|
str += String.fromCharCode(data[i]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var dataBase64 = window.btoa(str); |
|
|
|
|
|
|
|
var fontName = this.name; |
|
|
|
var fontName = this.name; |
|
|
|
|
|
|
|
|
|
|
|
/** Hack begin */ |
|
|
|
/** Hack begin */ |
|
|
|
|
|
|
|
|
|
|
|
// Actually there is not event when a font has finished downloading so
|
|
|
|
// Actually there is not event when a font has finished downloading so
|
|
|
|
// the following tons of code are a dirty hack to 'guess' when a font is
|
|
|
|
// the following code are a dirty hack to 'guess' when a font is ready
|
|
|
|
// ready
|
|
|
|
|
|
|
|
var debug = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (debug) { |
|
|
|
|
|
|
|
var name = document.createElement("font"); |
|
|
|
|
|
|
|
name.setAttribute("style", "position: absolute; left: 20px; top: " + |
|
|
|
|
|
|
|
(100 * fontCount + 60) + "px"); |
|
|
|
|
|
|
|
name.innerHTML = fontName; |
|
|
|
|
|
|
|
document.body.appendChild(name); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var canvas = document.createElement("canvas"); |
|
|
|
var canvas = document.createElement("canvas"); |
|
|
|
var style = "border: 1px solid black; position:absolute; top: " + |
|
|
|
var style = "border: 1px solid black; position:absolute; top: " + |
|
|
|
(debug ? (100 * fontCount) : "-200") + "px; left: 2px; width: 340px; height: 100px"; |
|
|
|
(debug ? (100 * fontCount) : "-200") + "px; left: 2px; width: 340px; height: 100px"; |
|
|
@ -201,33 +185,42 @@ var Font = (function () { |
|
|
|
canvas.setAttribute("heigth", 100); |
|
|
|
canvas.setAttribute("heigth", 100); |
|
|
|
document.body.appendChild(canvas); |
|
|
|
document.body.appendChild(canvas); |
|
|
|
|
|
|
|
|
|
|
|
// Retrieve font charset
|
|
|
|
|
|
|
|
var charset = Fonts[fontName].properties.charset || []; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if the charset is too small make it repeat a few times
|
|
|
|
|
|
|
|
var count = 30; |
|
|
|
|
|
|
|
while (count-- && charset.length <= 30) |
|
|
|
|
|
|
|
charset = charset.concat(charset.slice()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get the font size canvas think it will be for 'spaces'
|
|
|
|
// Get the font size canvas think it will be for 'spaces'
|
|
|
|
var ctx = canvas.getContext("2d"); |
|
|
|
var ctx = canvas.getContext("2d"); |
|
|
|
var testString = " "; |
|
|
|
ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial"; |
|
|
|
|
|
|
|
var testString = " "; |
|
|
|
|
|
|
|
|
|
|
|
// When debugging use the characters provided by the charsets to visually
|
|
|
|
// When debugging use the characters provided by the charsets to visually
|
|
|
|
// see what's happening
|
|
|
|
// see what's happening instead of 'spaces'
|
|
|
|
|
|
|
|
var debug = false; |
|
|
|
if (debug) { |
|
|
|
if (debug) { |
|
|
|
|
|
|
|
var name = document.createElement("font"); |
|
|
|
|
|
|
|
name.setAttribute("style", "position: absolute; left: 20px; top: " + |
|
|
|
|
|
|
|
(100 * fontCount + 60) + "px"); |
|
|
|
|
|
|
|
name.innerHTML = fontName; |
|
|
|
|
|
|
|
document.body.appendChild(name); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Retrieve font charset
|
|
|
|
|
|
|
|
var charset = Fonts[fontName].properties.charset || []; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if the charset is too small make it repeat a few times
|
|
|
|
|
|
|
|
var count = 30; |
|
|
|
|
|
|
|
while (count-- && charset.length <= 30) |
|
|
|
|
|
|
|
charset = charset.concat(charset.slice()); |
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < charset.length; i++) { |
|
|
|
for (var i = 0; i < charset.length; i++) { |
|
|
|
var unicode = GlyphsUnicode[charset[i]]; |
|
|
|
var unicode = GlyphsUnicode[charset[i]]; |
|
|
|
if (!unicode) |
|
|
|
if (!unicode) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
testString += String.fromCharCode(unicode); |
|
|
|
testString += String.fromCharCode(unicode); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial"; |
|
|
|
|
|
|
|
var textWidth = ctx.measureText(testString).width; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (debug) |
|
|
|
|
|
|
|
ctx.fillText(testString, 20, 20); |
|
|
|
ctx.fillText(testString, 20, 20); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Periodicaly check for the width of the testString, it will be
|
|
|
|
|
|
|
|
// different once the real font has loaded
|
|
|
|
|
|
|
|
var textWidth = ctx.measureText(testString).width; |
|
|
|
|
|
|
|
|
|
|
|
var interval = window.setInterval(function canvasInterval(self) { |
|
|
|
var interval = window.setInterval(function canvasInterval(self) { |
|
|
|
this.start = this.start || Date.now(); |
|
|
|
this.start = this.start || Date.now(); |
|
|
@ -248,12 +241,20 @@ var Font = (function () { |
|
|
|
|
|
|
|
|
|
|
|
if (debug) |
|
|
|
if (debug) |
|
|
|
ctx.fillText(testString, 20, 50); |
|
|
|
ctx.fillText(testString, 20, 50); |
|
|
|
}, 50, this); |
|
|
|
}, 30, this); |
|
|
|
|
|
|
|
|
|
|
|
/** Hack end */ |
|
|
|
/** Hack end */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get the base64 encoding of the binary font data
|
|
|
|
|
|
|
|
var str = ""; |
|
|
|
|
|
|
|
var length = data.length; |
|
|
|
|
|
|
|
for (var i = 0; i < length; ++i) |
|
|
|
|
|
|
|
str += String.fromCharCode(data[i]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var base64 = window.btoa(str); |
|
|
|
|
|
|
|
|
|
|
|
// Add the @font-face rule to the document
|
|
|
|
// Add the @font-face rule to the document
|
|
|
|
var url = "url(data:" + this.mimetype + ";base64," + dataBase64 + ");"; |
|
|
|
var url = "url(data:" + this.mimetype + ";base64," + base64 + ");"; |
|
|
|
var rule = "@font-face { font-family:'" + fontName + "';src:" + url + "}"; |
|
|
|
var rule = "@font-face { font-family:'" + fontName + "';src:" + url + "}"; |
|
|
|
var styleSheet = document.styleSheets[0]; |
|
|
|
var styleSheet = document.styleSheets[0]; |
|
|
|
styleSheet.insertRule(rule, styleSheet.length); |
|
|
|
styleSheet.insertRule(rule, styleSheet.length); |
|
|
@ -262,20 +263,23 @@ var Font = (function () { |
|
|
|
cover: function font_cover(aName, aFont, aProperties) { |
|
|
|
cover: function font_cover(aName, aFont, aProperties) { |
|
|
|
var otf = Uint8Array(kMaxFontFileSize); |
|
|
|
var otf = Uint8Array(kMaxFontFileSize); |
|
|
|
|
|
|
|
|
|
|
|
function s2a(s) { |
|
|
|
function stringToArray(str) { |
|
|
|
var a = []; |
|
|
|
var array = []; |
|
|
|
for (var i = 0; i < s.length; ++i) |
|
|
|
for (var i = 0; i < str.length; ++i) |
|
|
|
a[i] = s.charCodeAt(i); |
|
|
|
array[i] = str.charCodeAt(i); |
|
|
|
return a; |
|
|
|
return array; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function s16(value) { |
|
|
|
function string16(value) { |
|
|
|
return String.fromCharCode((value >> 8) & 0xff) + String.fromCharCode(value & 0xff); |
|
|
|
return String.fromCharCode((value >> 8) & 0xff) + |
|
|
|
|
|
|
|
String.fromCharCode(value & 0xff); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function s32(value) { |
|
|
|
function string32(value) { |
|
|
|
return String.fromCharCode((value >> 24) & 0xff) + String.fromCharCode((value >> 16) & 0xff) + |
|
|
|
return String.fromCharCode((value >> 24) & 0xff) + |
|
|
|
String.fromCharCode((value >> 8) & 0xff) + String.fromCharCode(value & 0xff); |
|
|
|
String.fromCharCode((value >> 16) & 0xff) + |
|
|
|
|
|
|
|
String.fromCharCode((value >> 8) & 0xff) + |
|
|
|
|
|
|
|
String.fromCharCode(value & 0xff); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function createOpenTypeHeader(aFile, aOffsets, numTables) { |
|
|
|
function createOpenTypeHeader(aFile, aOffsets, numTables) { |
|
|
@ -285,20 +289,20 @@ var Font = (function () { |
|
|
|
header += "\x4F\x54\x54\x4F"; |
|
|
|
header += "\x4F\x54\x54\x4F"; |
|
|
|
|
|
|
|
|
|
|
|
// numTables (2 bytes)
|
|
|
|
// numTables (2 bytes)
|
|
|
|
header += s16(numTables); |
|
|
|
header += string16(numTables); |
|
|
|
|
|
|
|
|
|
|
|
// searchRange (2 bytes)
|
|
|
|
// searchRange (2 bytes)
|
|
|
|
var tablesMaxPower2 = FontsUtils.getMaxPower2(numTables); |
|
|
|
var tablesMaxPower2 = FontsUtils.getMaxPower2(numTables); |
|
|
|
var searchRange = tablesMaxPower2 * 16; |
|
|
|
var searchRange = tablesMaxPower2 * 16; |
|
|
|
header += s16(searchRange); |
|
|
|
header += string16(searchRange); |
|
|
|
|
|
|
|
|
|
|
|
// entrySelector (2 bytes)
|
|
|
|
// entrySelector (2 bytes)
|
|
|
|
header += s16(Math.log(tablesMaxPower2) / Math.log(2)); |
|
|
|
header += string16(Math.log(tablesMaxPower2) / Math.log(2)); |
|
|
|
|
|
|
|
|
|
|
|
// rangeShift (2 bytes)
|
|
|
|
// rangeShift (2 bytes)
|
|
|
|
header += s16(numTables * 16 - searchRange); |
|
|
|
header += string16(numTables * 16 - searchRange); |
|
|
|
|
|
|
|
|
|
|
|
aFile.set(s2a(header), aOffsets.currentOffset); |
|
|
|
aFile.set(stringToArray(header), aOffsets.currentOffset); |
|
|
|
aOffsets.currentOffset += header.length; |
|
|
|
aOffsets.currentOffset += header.length; |
|
|
|
aOffsets.virtualOffset += header.length; |
|
|
|
aOffsets.virtualOffset += header.length; |
|
|
|
} |
|
|
|
} |
|
|
@ -322,25 +326,27 @@ var Font = (function () { |
|
|
|
offset + |
|
|
|
offset + |
|
|
|
length; |
|
|
|
length; |
|
|
|
|
|
|
|
|
|
|
|
var tableEntry = aTag + s32(checksum) + s32(offset) + s32(length); |
|
|
|
var tableEntry = aTag + string32(checksum) + string32(offset) + string32(length); |
|
|
|
tableEntry = s2a(tableEntry); |
|
|
|
tableEntry = stringToArray(tableEntry); |
|
|
|
aFile.set(tableEntry, aOffsets.currentOffset); |
|
|
|
aFile.set(tableEntry, aOffsets.currentOffset); |
|
|
|
|
|
|
|
|
|
|
|
aOffsets.currentOffset += tableEntry.length; |
|
|
|
aOffsets.currentOffset += tableEntry.length; |
|
|
|
aOffsets.virtualOffset += aData.length; |
|
|
|
aOffsets.virtualOffset += aData.length; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function createNameTable(aName) { |
|
|
|
function createNameTable(aName) { |
|
|
|
var names = |
|
|
|
var names = [ |
|
|
|
"See original licence" + // Copyright
|
|
|
|
"See original licence", // Copyright
|
|
|
|
aName + // Font family
|
|
|
|
aName, // Font family
|
|
|
|
"undefined" + // Font subfamily (font weight)
|
|
|
|
"undefined", // Font subfamily (font weight)
|
|
|
|
"uniqueID" + // Unique ID
|
|
|
|
"uniqueID", // Unique ID
|
|
|
|
aName + // Full font name
|
|
|
|
aName, // Full font name
|
|
|
|
"0.1" + // Version
|
|
|
|
"0.1", // Version
|
|
|
|
"undefined" + // Postscript name
|
|
|
|
"undefined", // Postscript name
|
|
|
|
"undefined" + // Trademark
|
|
|
|
"undefined", // Trademark
|
|
|
|
"undefined" + // Manufacturer
|
|
|
|
"undefined", // Manufacturer
|
|
|
|
"undefined"; // Designer
|
|
|
|
"undefined" // Designer
|
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
var name = |
|
|
|
var name = |
|
|
|
"\x00\x00" + // format
|
|
|
|
"\x00\x00" + // format
|
|
|
@ -357,14 +363,14 @@ var Font = (function () { |
|
|
|
"\x00\x00" + // encoding ID
|
|
|
|
"\x00\x00" + // encoding ID
|
|
|
|
"\x00\x00" + // language ID
|
|
|
|
"\x00\x00" + // language ID
|
|
|
|
"\x00\x00" + // name ID
|
|
|
|
"\x00\x00" + // name ID
|
|
|
|
s16(str.length) + |
|
|
|
string16(str.length) + |
|
|
|
s16(strOffset); |
|
|
|
string16(strOffset); |
|
|
|
name += nameRecord; |
|
|
|
name += nameRecord; |
|
|
|
|
|
|
|
|
|
|
|
strOffset += str.length; |
|
|
|
strOffset += str.length; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
name += names; |
|
|
|
name += names.join(""); |
|
|
|
return name; |
|
|
|
return name; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -407,12 +413,12 @@ var Font = (function () { |
|
|
|
"\x00\x01" + // encodingID
|
|
|
|
"\x00\x01" + // encodingID
|
|
|
|
"\x00\x00\x00\x0C" + // start of the table record
|
|
|
|
"\x00\x00\x00\x0C" + // start of the table record
|
|
|
|
"\x00\x04" + // format
|
|
|
|
"\x00\x04" + // format
|
|
|
|
s16(headerSize) + // length
|
|
|
|
string16(headerSize) + // length
|
|
|
|
"\x00\x00" + // languages
|
|
|
|
"\x00\x00" + // languages
|
|
|
|
s16(segCount2) + |
|
|
|
string16(segCount2) + |
|
|
|
s16(searchRange) + |
|
|
|
string16(searchRange) + |
|
|
|
s16(searchEntry) + |
|
|
|
string16(searchEntry) + |
|
|
|
s16(rangeShift); |
|
|
|
string16(rangeShift); |
|
|
|
|
|
|
|
|
|
|
|
// Fill up the 4 parallel arrays describing the segments.
|
|
|
|
// Fill up the 4 parallel arrays describing the segments.
|
|
|
|
var startCount = ""; |
|
|
|
var startCount = ""; |
|
|
@ -428,10 +434,10 @@ var Font = (function () { |
|
|
|
var delta = (((start - 1) - bias) ^ 0xffff) + 1; |
|
|
|
var delta = (((start - 1) - bias) ^ 0xffff) + 1; |
|
|
|
bias += (end - start + 1); |
|
|
|
bias += (end - start + 1); |
|
|
|
|
|
|
|
|
|
|
|
startCount += s16(start); |
|
|
|
startCount += string16(start); |
|
|
|
endCount += s16(end); |
|
|
|
endCount += string16(end); |
|
|
|
idDeltas += s16(delta); |
|
|
|
idDeltas += string16(delta); |
|
|
|
idRangeOffsets += s16(0); |
|
|
|
idRangeOffsets += string16(0); |
|
|
|
|
|
|
|
|
|
|
|
for (var j = start; j <= end; j++) |
|
|
|
for (var j = start; j <= end; j++) |
|
|
|
glyphsIds += String.fromCharCode(j); |
|
|
|
glyphsIds += String.fromCharCode(j); |
|
|
@ -442,7 +448,7 @@ var Font = (function () { |
|
|
|
idDeltas += "\x00\x01"; |
|
|
|
idDeltas += "\x00\x01"; |
|
|
|
idRangeOffsets += "\x00\x00"; |
|
|
|
idRangeOffsets += "\x00\x00"; |
|
|
|
|
|
|
|
|
|
|
|
return s2a(cmap + endCount + "\x00\x00" + startCount + |
|
|
|
return stringToArray(cmap + endCount + "\x00\x00" + startCount + |
|
|
|
idDeltas + idRangeOffsets + glyphsIds); |
|
|
|
idDeltas + idRangeOffsets + glyphsIds); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -477,7 +483,7 @@ var Font = (function () { |
|
|
|
createTableEntry(otf, offsets, "CFF ", CFF); |
|
|
|
createTableEntry(otf, offsets, "CFF ", CFF); |
|
|
|
|
|
|
|
|
|
|
|
/** OS/2 */ |
|
|
|
/** OS/2 */ |
|
|
|
OS2 = s2a( |
|
|
|
OS2 = stringToArray( |
|
|
|
"\x00\x03" + // version
|
|
|
|
"\x00\x03" + // version
|
|
|
|
"\x02\x24" + // xAvgCharWidth
|
|
|
|
"\x02\x24" + // xAvgCharWidth
|
|
|
|
"\x01\xF4" + // usWeightClass
|
|
|
|
"\x01\xF4" + // usWeightClass
|
|
|
@ -526,7 +532,7 @@ var Font = (function () { |
|
|
|
createTableEntry(otf, offsets, "cmap", cmap); |
|
|
|
createTableEntry(otf, offsets, "cmap", cmap); |
|
|
|
|
|
|
|
|
|
|
|
/** HEAD */ |
|
|
|
/** HEAD */ |
|
|
|
head = s2a( |
|
|
|
head = stringToArray( |
|
|
|
"\x00\x01\x00\x00" + // Version number
|
|
|
|
"\x00\x01\x00\x00" + // Version number
|
|
|
|
"\x00\x00\x50\x00" + // fontRevision
|
|
|
|
"\x00\x00\x50\x00" + // fontRevision
|
|
|
|
"\x00\x00\x00\x00" + // checksumAdjustement
|
|
|
|
"\x00\x00\x00\x00" + // checksumAdjustement
|
|
|
@ -548,7 +554,7 @@ var Font = (function () { |
|
|
|
createTableEntry(otf, offsets, "head", head); |
|
|
|
createTableEntry(otf, offsets, "head", head); |
|
|
|
|
|
|
|
|
|
|
|
/** HHEA */ |
|
|
|
/** HHEA */ |
|
|
|
hhea = s2a( |
|
|
|
hhea = stringToArray( |
|
|
|
"\x00\x01\x00\x00" + // Version number
|
|
|
|
"\x00\x01\x00\x00" + // Version number
|
|
|
|
"\x00\x00" + // Typographic Ascent
|
|
|
|
"\x00\x00" + // Typographic Ascent
|
|
|
|
"\x00\x00" + // Typographic Descent
|
|
|
|
"\x00\x00" + // Typographic Descent
|
|
|
@ -565,7 +571,7 @@ var Font = (function () { |
|
|
|
"\x00\x00" + // -reserved-
|
|
|
|
"\x00\x00" + // -reserved-
|
|
|
|
"\x00\x00" + // -reserved-
|
|
|
|
"\x00\x00" + // -reserved-
|
|
|
|
"\x00\x00" + // metricDataFormat
|
|
|
|
"\x00\x00" + // metricDataFormat
|
|
|
|
s16(charstrings.length) |
|
|
|
string16(charstrings.length) |
|
|
|
); |
|
|
|
); |
|
|
|
createTableEntry(otf, offsets, "hhea", hhea); |
|
|
|
createTableEntry(otf, offsets, "hhea", hhea); |
|
|
|
|
|
|
|
|
|
|
@ -575,19 +581,19 @@ var Font = (function () { |
|
|
|
var charstring = charstrings[i].charstring; |
|
|
|
var charstring = charstrings[i].charstring; |
|
|
|
var width = charstring[1]; |
|
|
|
var width = charstring[1]; |
|
|
|
var lsb = charstring[0]; |
|
|
|
var lsb = charstring[0]; |
|
|
|
hmtx += s16(width) + s16(lsb); |
|
|
|
hmtx += string16(width) + string16(lsb); |
|
|
|
} |
|
|
|
} |
|
|
|
hmtx = s2a(hmtx); |
|
|
|
hmtx = stringToArray(hmtx); |
|
|
|
createTableEntry(otf, offsets, "hmtx", hmtx); |
|
|
|
createTableEntry(otf, offsets, "hmtx", hmtx); |
|
|
|
|
|
|
|
|
|
|
|
/** MAXP */ |
|
|
|
/** MAXP */ |
|
|
|
maxp = "\x00\x00\x50\x00" + // Version number
|
|
|
|
maxp = "\x00\x00\x50\x00" + // Version number
|
|
|
|
s16(charstrings.length + 1); // Num of glyphs (+1 to pass the sanitizer...)
|
|
|
|
string16(charstrings.length + 1); // Num of glyphs (+1 to pass the sanitizer...)
|
|
|
|
maxp = s2a(maxp); |
|
|
|
maxp = stringToArray(maxp); |
|
|
|
createTableEntry(otf, offsets, "maxp", maxp); |
|
|
|
createTableEntry(otf, offsets, "maxp", maxp); |
|
|
|
|
|
|
|
|
|
|
|
/** NAME */ |
|
|
|
/** NAME */ |
|
|
|
name = s2a(createNameTable(aName)); |
|
|
|
name = stringToArray(createNameTable(aName)); |
|
|
|
createTableEntry(otf, offsets, "name", name); |
|
|
|
createTableEntry(otf, offsets, "name", name); |
|
|
|
|
|
|
|
|
|
|
|
/** POST */ |
|
|
|
/** POST */ |
|
|
@ -601,7 +607,7 @@ var Font = (function () { |
|
|
|
"\x00\x00\x00\x00" + // maxMemType42
|
|
|
|
"\x00\x00\x00\x00" + // maxMemType42
|
|
|
|
"\x00\x00\x00\x00" + // minMemType1
|
|
|
|
"\x00\x00\x00\x00" + // minMemType1
|
|
|
|
"\x00\x00\x00\x00"; // maxMemType1
|
|
|
|
"\x00\x00\x00\x00"; // maxMemType1
|
|
|
|
post = s2a(post); |
|
|
|
post = stringToArray(post); |
|
|
|
createTableEntry(otf, offsets, "post", post); |
|
|
|
createTableEntry(otf, offsets, "post", post); |
|
|
|
|
|
|
|
|
|
|
|
// Once all the table entries header are written, dump the data!
|
|
|
|
// Once all the table entries header are written, dump the data!
|
|
|
@ -622,6 +628,7 @@ var Font = (function () { |
|
|
|
return constructor; |
|
|
|
return constructor; |
|
|
|
})(); |
|
|
|
})(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* FontsUtils is a static class dedicated to hold codes that are not related |
|
|
|
* FontsUtils is a static class dedicated to hold codes that are not related |
|
|
|
* to fonts in particular and needs to be share between them. |
|
|
|
* to fonts in particular and needs to be share between them. |
|
|
@ -1300,6 +1307,10 @@ var Type1Parser = function() { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* The CFF class takes a Type1 file and wrap it into a 'Compact Font Format', |
|
|
|
|
|
|
|
* which itself embed Type2 charstrings. |
|
|
|
|
|
|
|
*/ |
|
|
|
const CFFStrings = [ |
|
|
|
const CFFStrings = [ |
|
|
|
".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand", |
|
|
|
".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand", |
|
|
|
"quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period", |
|
|
|
"quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period", |
|
|
@ -1358,10 +1369,6 @@ const CFFStrings = [ |
|
|
|
"001.003","Black","Bold","Book","Light","Medium","Regular","Roman","Semibold" |
|
|
|
"001.003","Black","Bold","Book","Light","Medium","Regular","Roman","Semibold" |
|
|
|
]; |
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Take a Type1 file as input and wrap it into a Compact Font Format (CFF) |
|
|
|
|
|
|
|
* wrapping Type2 charstrings. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
var CFF = function(aName, aFile, aProperties) { |
|
|
|
var CFF = function(aName, aFile, aProperties) { |
|
|
|
// Get the data block containing glyphs and subrs informations
|
|
|
|
// Get the data block containing glyphs and subrs informations
|
|
|
|
var length1 = aFile.dict.get("Length1"); |
|
|
|
var length1 = aFile.dict.get("Length1"); |
|
|
|