From 688d7f28f85fa609db8a47a5984f5d4ac4d41217 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Mon, 4 Jul 2011 03:42:48 +0200
Subject: [PATCH 01/20] Fix a few warnings
---
fonts.js | 181 +++++++++++++++++++++++++++++--------------------------
1 file changed, 96 insertions(+), 85 deletions(-)
diff --git a/fonts.js b/fonts.js
index 12d7ce82e..23c7699dd 100644
--- a/fonts.js
+++ b/fonts.js
@@ -67,7 +67,7 @@ var Fonts = (function Fonts() {
markLoaded(fontName);
},
lookup: function fonts_lookup(fontName) {
- return fonts[fontName];
+ return (fontName in fonts) ? fonts[fontName] : null;
},
setActive: function fonts_setActive(fontName, size) {
current = fonts[fontName];
@@ -126,7 +126,7 @@ var Fonts = (function Fonts() {
var FontLoader = {
listeningForFontLoad: false,
- bind: function(fonts, callback) {
+ bind: function font_bind(fonts, callback) {
function checkFontsLoaded() {
for (var i = 0; i < fonts.length; i++) {
var font = fonts[i];
@@ -178,7 +178,7 @@ var FontLoader = {
// loaded in a subdocument. It's expected that the load of |rules|
// has already started in this (outer) document, so that they should
// be ordered before the load in the subdocument.
- prepareFontLoadEvent: function(rules, names) {
+ prepareFontLoadEvent: function prepareFontLoadEvent(rules, names) {
/** Hack begin */
// There's no event when a font has finished downloading so the
// following code is a dirty hack to 'guess' when a font is
@@ -412,7 +412,7 @@ function getUnicodeRangeFor(value) {
* var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
* type1Font.bind();
*/
-var Font = (function () {
+var Font = (function Font() {
var constructor = function font_constructor(name, file, properties) {
this.name = name;
this.encoding = properties.encoding;
@@ -543,7 +543,11 @@ var Font = (function () {
for (var i = 0; i < length; i+=4)
checksum += int16([data[i], data[i+1], data[i+2], data[i+3]]);
- var tableEntry = tag + string32(checksum) + string32(offset) + string32(length);
+ var tableEntry = tag +
+ string32(checksum) +
+ string32(offset) +
+ string32(length);
+
tableEntry = stringToArray(tableEntry);
file.set(tableEntry, offsets.currentOffset);
@@ -783,7 +787,7 @@ var Font = (function () {
(format == 6 && numTables == 1 && !properties.encoding.empty)) {
// Format 0 alone is not allowed by the sanitizer so let's rewrite
// that to a 3-1-4 Unicode BMP table
- TODO("Use an other source of informations than charset here, it is not reliable");
+ TODO("Charset is not reliable, use somethin else");
var charset = properties.charset;
var glyphs = [];
for (var j = 0; j < charset.length; j++) {
@@ -823,8 +827,9 @@ var Font = (function () {
for (var j = 0; j < glyphs.length; j++)
glyphs[j] = { unicode: glyphs[j] + firstCode };
- var ranges= getRanges(glyphs);
- assert(ranges.length == 1, "Got " + ranges.length + " ranges in a dense array");
+ var ranges = getRanges(glyphs);
+ assert(ranges.length == 1,
+ "Got " + ranges.length + " ranges in a dense array");
var encoding = properties.encoding;
var denseRange = ranges[0];
@@ -1041,7 +1046,7 @@ var Font = (function () {
"cmap": createCMapTable(charstrings.slice()),
// Font header
- "head": (function() {
+ "head": (function convert_fields_head() {
return stringToArray(
"\x00\x01\x00\x00" + // Version number
"\x00\x00\x10\x00" + // fontRevision
@@ -1063,7 +1068,7 @@ var Font = (function () {
})(),
// Horizontal header
- "hhea": (function() {
+ "hhea": (function convert_fields_hhea() {
return stringToArray(
"\x00\x01\x00\x00" + // Version number
string16(properties.ascent) + // Typographic Ascent
@@ -1085,7 +1090,7 @@ var Font = (function () {
})(),
// Horizontal metrics
- "hmtx": (function() {
+ "hmtx": (function convert_fields_hmtx() {
var hmtx = "\x00\x00\x00\x00"; // Fake .notdef
for (var i = 0; i < charstrings.length; i++) {
hmtx += string16(charstrings[i].width) + string16(0);
@@ -1094,7 +1099,7 @@ var Font = (function () {
})(),
// Maximum profile
- "maxp": (function() {
+ "maxp": (function convert_fields_maxp() {
return stringToArray(
"\x00\x00\x50\x00" + // Version number
string16(charstrings.length + 1)); // Num of glyphs
@@ -1134,14 +1139,11 @@ var Font = (function () {
},
bindDOM: function font_bindDom(data) {
- var fontName = this.name;
-
- // Add the @font-face rule to the document
var url = "url(data:" + this.mimetype + ";base64," + window.btoa(data) + ");";
- var rule = "@font-face { font-family:'" + fontName + "';src:" + url + "}";
+ var rule = "@font-face { font-family:'" + this.name + "';src:" + url + "}";
+
var styleSheet = document.styleSheets[0];
styleSheet.insertRule(rule, styleSheet.cssRules.length);
-
return rule;
}
};
@@ -1154,7 +1156,7 @@ var Font = (function () {
* program.
* Some of its logic depends on the Type2 charstrings structure.
*/
-var Type1Parser = function() {
+var Type1Parser = function Type1Parser() {
/*
* Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence
* of Plaintext Bytes. The function took a key as a parameter which can be
@@ -1344,7 +1346,9 @@ var Type1Parser = function() {
} else if (!command) {
break;
} else if (command == -1) {
- error("Support for Type1 command " + value + " (" + escape + ") is not implemented in charstring: " + charString);
+ error("Support for Type1 command " +
+ value + " (" + escape + ")" +
+ " is not implemented in charstring: " + charString);
}
value = command;
@@ -1369,7 +1373,7 @@ var Type1Parser = function() {
* Returns an object containing a Subrs array and a CharStrings array
* extracted from and eexec encrypted block of data
*/
- function readNumberArray(str, index) {
+ function readNumbers(str, index) {
var start = ++index;
var count = 0;
while (str[index++] != "]")
@@ -1436,16 +1440,16 @@ var Type1Parser = function() {
subrsSection = true;
break;
case "/StdHW":
- extracted.properties.stdHW = readNumberArray(eexecString, i + 2)[0];
+ extracted.properties.stdHW = readNumbers(eexecString, i + 2)[0];
break;
case "/StdVW":
- extracted.properties.stdVW = readNumberArray(eexecString, i + 2)[0];
+ extracted.properties.stdVW = readNumbers(eexecString, i + 2)[0];
break;
case "/StemSnapH":
- extracted.properties.stemSnapH = readNumberArray(eexecString, i + 2);
+ extracted.properties.stemSnapH = readNumbers(eexecString, i + 2);
break;
case "/StemSnapV":
- extracted.properties.stemSnapV = readNumberArray(eexecString, i + 2);
+ extracted.properties.stemSnapV = readNumbers(eexecString, i + 2);
break;
}
} else if (c == "/") {
@@ -1475,7 +1479,7 @@ var Type1Parser = function() {
if (c == " " || c == "\n") {
switch (token) {
case "/FontMatrix":
- var matrix = readNumberArray(headerString, i + 1);
+ var matrix = readNumbers(headerString, i + 1);
// The FontMatrix is in unitPerEm, so make it pixels
for (var j = 0; j < matrix.length; j++)
@@ -1502,66 +1506,70 @@ var Type1Parser = function() {
* which itself embed Type2 charstrings.
*/
var CFFStrings = [
- ".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand",
- "quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period",
- "slash","zero","one","two","three","four","five","six","seven","eight","nine",
- "colon","semicolon","less","equal","greater","question","at","A","B","C","D","E",
- "F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y",
- "Z","bracketleft","backslash","bracketright","asciicircum","underscore",
- "quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q",
- "r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde",
- "exclamdown","cent","sterling","fraction","yen","florin","section","currency",
- "quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright",
- "fi","fl","endash","dagger","daggerdbl","periodcentered","paragraph","bullet",
+ ".notdef","space","exclam","quotedbl","numbersign","dollar","percent",
+ "ampersand","quoteright","parenleft","parenright","asterisk","plus","comma",
+ "hyphen","period","slash","zero","one","two","three","four","five","six",
+ "seven","eight","nine","colon","semicolon","less","equal","greater",
+ "question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
+ "P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash",
+ "bracketright","asciicircum","underscore","quoteleft","a","b","c","d","e",
+ "f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x",
+ "y","z","braceleft","bar","braceright","asciitilde","exclamdown","cent",
+ "sterling","fraction","yen","florin","section","currency","quotesingle",
+ "quotedblleft","guillemotleft","guilsinglleft","guilsinglright","fi","fl",
+ "endash","dagger","daggerdbl","periodcentered","paragraph","bullet",
"quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis",
"perthousand","questiondown","grave","acute","circumflex","tilde","macron",
- "breve","dotaccent","dieresis","ring","cedilla","hungarumlaut","ogonek","caron",
- "emdash","AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae","dotlessi",
- "lslash","oslash","oe","germandbls","onesuperior","logicalnot","mu","trademark",
- "Eth","onehalf","plusminus","Thorn","onequarter","divide","brokenbar","degree",
- "thorn","threequarters","twosuperior","registered","minus","eth","multiply",
- "threesuperior","copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring",
+ "breve","dotaccent","dieresis","ring","cedilla","hungarumlaut","ogonek",
+ "caron","emdash","AE","ordfeminine","Lslash","Oslash","OE","ordmasculine",
+ "ae","dotlessi","lslash","oslash","oe","germandbls","onesuperior",
+ "logicalnot","mu","trademark","Eth","onehalf","plusminus","Thorn",
+ "onequarter","divide","brokenbar","degree","thorn","threequarters",
+ "twosuperior","registered","minus","eth","multiply","threesuperior",
+ "copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring",
"Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave","Iacute",
- "Icircumflex","Idieresis","Igrave","Ntilde","Oacute","Ocircumflex","Odieresis",
- "Ograve","Otilde","Scaron","Uacute","Ucircumflex","Udieresis","Ugrave","Yacute",
- "Ydieresis","Zcaron","aacute","acircumflex","adieresis","agrave","aring","atilde",
- "ccedilla","eacute","ecircumflex","edieresis","egrave","iacute","icircumflex",
- "idieresis","igrave","ntilde","oacute","ocircumflex","odieresis","ograve",
- "otilde","scaron","uacute","ucircumflex","udieresis","ugrave","yacute",
- "ydieresis","zcaron","exclamsmall","Hungarumlautsmall","dollaroldstyle",
- "dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior",
- "parenrightsuperior","266 ff","onedotenleader","zerooldstyle","oneoldstyle",
- "twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle",
- "sevenoldstyle","eightoldstyle","nineoldstyle","commasuperior",
- "threequartersemdash","periodsuperior","questionsmall","asuperior","bsuperior",
- "centsuperior","dsuperior","esuperior","isuperior","lsuperior","msuperior",
- "nsuperior","osuperior","rsuperior","ssuperior","tsuperior","ff","ffi","ffl",
- "parenleftinferior","parenrightinferior","Circumflexsmall","hyphensuperior",
- "Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall",
- "Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall",
- "Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall",
- "Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","exclamdownsmall",
- "centoldstyle","Lslashsmall","Scaronsmall","Zcaronsmall","Dieresissmall",
- "Brevesmall","Caronsmall","Dotaccentsmall","Macronsmall","figuredash",
- "hypheninferior","Ogoneksmall","Ringsmall","Cedillasmall","questiondownsmall",
- "oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds",
- "zerosuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior",
- "eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior",
- "threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior",
- "eightinferior","nineinferior","centinferior","dollarinferior","periodinferior",
- "commainferior","Agravesmall","Aacutesmall","Acircumflexsmall","Atildesmall",
- "Adieresissmall","Aringsmall","AEsmall","Ccedillasmall","Egravesmall",
- "Eacutesmall","Ecircumflexsmall","Edieresissmall","Igravesmall","Iacutesmall",
- "Icircumflexsmall","Idieresissmall","Ethsmall","Ntildesmall","Ogravesmall",
- "Oacutesmall","Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall",
- "Oslashsmall","Ugravesmall","Uacutesmall","Ucircumflexsmall","Udieresissmall",
+ "Icircumflex","Idieresis","Igrave","Ntilde","Oacute","Ocircumflex",
+ "Odieresis","Ograve","Otilde","Scaron","Uacute","Ucircumflex","Udieresis",
+ "Ugrave","Yacute","Ydieresis","Zcaron","aacute","acircumflex","adieresis",
+ "agrave","aring","atilde","ccedilla","eacute","ecircumflex","edieresis",
+ "egrave","iacute","icircumflex","idieresis","igrave","ntilde","oacute",
+ "ocircumflex","odieresis","ograve","otilde","scaron","uacute","ucircumflex",
+ "udieresis","ugrave","yacute","ydieresis","zcaron","exclamsmall",
+ "Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall",
+ "Acutesmall","parenleftsuperior","parenrightsuperior","206 ff",
+ "onedotenleader","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle",
+ "fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle",
+ "nineoldstyle","commasuperior","threequartersemdash","periodsuperior",
+ "questionsmall","asuperior","bsuperior","centsuperior","dsuperior",
+ "esuperior","isuperior","lsuperior","msuperior", "nsuperior","osuperior",
+ "rsuperior","ssuperior","tsuperior","ff","ffi","ffl","parenleftinferior",
+ "parenrightinferior","Circumflexsmall","hyphensuperior","Gravesmall",
+ "Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall",
+ "Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall",
+ "Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall",
+ "Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall",
+ "exclamdownsmall","centoldstyle","Lslashsmall","Scaronsmall","Zcaronsmall",
+ "Dieresissmall","Brevesmall","Caronsmall","Dotaccentsmall","Macronsmall",
+ "figuredash","hypheninferior","Ogoneksmall","Ringsmall","Cedillasmall",
+ "questiondownsmall","oneeighth","threeeighths","fiveeighths","seveneighths",
+ "onethird","twothirds","zerosuperior","foursuperior","fivesuperior",
+ "sixsuperior","sevensuperior","eightsuperior","ninesuperior","zeroinferior",
+ "oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior",
+ "sixinferior","seveninferior","eightinferior","nineinferior","centinferior",
+ "dollarinferior","periodinferior","commainferior","Agravesmall",
+ "Aacutesmall","Acircumflexsmall","Atildesmall","Adieresissmall","Aringsmall",
+ "AEsmall","Ccedillasmall","Egravesmall","Eacutesmall","Ecircumflexsmall",
+ "Edieresissmall","Igravesmall","Iacutesmall","Icircumflexsmall",
+ "Idieresissmall","Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall",
+ "Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall","Oslashsmall",
+ "Ugravesmall","Uacutesmall","Ucircumflexsmall","Udieresissmall",
"Yacutesmall","Thornsmall","Ydieresissmall","001.000","001.001","001.002",
"001.003","Black","Bold","Book","Light","Medium","Regular","Roman","Semibold"
];
var type1Parser = new Type1Parser();
-var CFF = function(name, file, properties) {
+var CFF = function CFF(name, file, properties) {
// Get the data block containing glyphs and subrs informations
var length1 = file.dict.get("Length1");
var length2 = file.dict.get("Length2");
@@ -1582,7 +1590,8 @@ var CFF = function(name, file, properties) {
var subrs = this.getType2Subrs(data.subrs);
this.charstrings = charstrings;
- this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties);
+ this.data = this.wrap(name, type2Charstrings,
+ this.charstrings, subrs, properties);
};
CFF.prototype = {
@@ -1643,7 +1652,7 @@ CFF.prototype = {
var unicode = GlyphsUnicode[glyph.glyph];
if (!unicode) {
if (glyph.glyph != ".notdef")
- warn(glyph + " does not have an entry in the glyphs unicode dictionary");
+ warn(glyph + " has no entry in the glyphs unicode dictionary");
} else {
charstrings.push({
glyph: glyph,
@@ -1666,7 +1675,8 @@ CFF.prototype = {
var count = type1Charstrings.length;
for (var i = 0; i < count; i++) {
var charstring = type1Charstrings[i].charstring;
- type2Charstrings.push(this.flattenCharstring(charstring.slice(), this.commandsMap));
+ var flate = this.flattenCharstring(charstring.slice(), this.commandsMap);
+ type2Charstrings.push(flate);
}
return type2Charstrings;
},
@@ -1738,12 +1748,13 @@ CFF.prototype = {
wrap: function wrap(name, glyphs, charstrings, subrs, properties) {
var fields = {
- "header": "\x01\x00\x04\x04", // major version, minor version, header size, offset size
+ // major version, minor version, header size, offset size
+ "header": "\x01\x00\x04\x04",
"names": this.createCFFIndexHeader([name]),
"topDict": (function topDict(self) {
- return function() {
+ return function wrap_inner_topDict() {
var dict =
"\x00\x01\x01\x01\x30" +
"\xf8\x1b\x00" + // version
@@ -1795,9 +1806,9 @@ CFF.prototype = {
var count = glyphs.length;
for (var i = 0; i < count; i++) {
var index = CFFStrings.indexOf(charstrings[i].glyph.glyph);
- // Some characters like asterikmath && circlecopyrt are missing from the
- // original strings, for the moment let's map them to .notdef and see
- // later if it cause any problems
+ // Some characters like asterikmath && circlecopyrt are missing from
+ // the original strings, for the moment let's map them to .notdef and
+ // see later if it cause any problems
if (index == -1)
index = 0;
@@ -1808,7 +1819,7 @@ CFF.prototype = {
"charstrings": this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs), true),
- "private": (function(self) {
+ "private": (function wrap_private(self) {
var data =
"\x8b\x14" + // defaultWidth
"\x8b\x15" + // nominalWidth
From 17803049a9636608e88a78d3a04f36930a3fd849 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Mon, 4 Jul 2011 03:57:25 +0200
Subject: [PATCH 02/20] Make 'cmap' declare the correct header size
---
fonts.js | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/fonts.js b/fonts.js
index 23c7699dd..8bee706b2 100644
--- a/fonts.js
+++ b/fonts.js
@@ -573,7 +573,7 @@ var Font = (function Font() {
++end;
++n;
}
- ranges.push([start, end]);
+ ranges.push({ start: start, end: end });
}
return ranges;
};
@@ -589,11 +589,11 @@ var Font = (function Font() {
"\x00\x01" + // encodingID
string32(4 + numTables * 8); // start of the table record
- var headerSize = (12 * 2 + (ranges.length * 5 * 2));
+ var headerSize = ((7 * 2) + (ranges.length * 4 * 2) + (4 * 2) + (glyphs.length * 2));
var segCount = ranges.length + 1;
- var segCount2 = segCount * 2;
- var searchRange = getMaxPower2(segCount) * 2;
- var searchEntry = Math.log(segCount) / Math.log(2);
+ var segCount2 = 2 * segCount;
+ var searchRange = 2 * getMaxPower2(segCount);
+ var entrySelector = Math.log(segCount) / Math.log(2);
var rangeShift = 2 * segCount - searchRange;
var format314 = "\x00\x04" + // format
@@ -601,7 +601,7 @@ var Font = (function Font() {
"\x00\x00" + // language
string16(segCount2) +
string16(searchRange) +
- string16(searchEntry) +
+ string16(entrySelector) +
string16(rangeShift);
// Fill up the 4 parallel arrays describing the segments.
@@ -613,8 +613,8 @@ var Font = (function Font() {
var bias = 0;
for (var i = 0; i < segCount - 1; i++) {
var range = ranges[i];
- var start = range[0];
- var end = range[1];
+ var start = range.start;
+ var end = range.end;
var delta = (bias - start) % 0xffff;
bias += (end - start + 1);
@@ -622,16 +622,15 @@ var Font = (function Font() {
endCount += string16(end);
idDeltas += string16(delta);
idRangeOffsets += string16(0);
-
- for (var j = start; j <= end; j++) {
- glyphsIds += string16(j);
- }
}
-
endCount += "\xFF\xFF";
startCount += "\xFF\xFF";
idDeltas += "\x00\x01";
idRangeOffsets += "\x00\x00";
+
+ for (var i = 0; i < glyphs.length; i++)
+ glyphsIds += string16(i);
+
format314 += endCount + "\x00\x00" + startCount +
idDeltas + idRangeOffsets + glyphsIds;
@@ -833,11 +832,12 @@ var Font = (function Font() {
var encoding = properties.encoding;
var denseRange = ranges[0];
- var start = denseRange[0];
- var end = denseRange[1];
+ var start = denseRange.start;
+ var end = denseRange.end;
var index = firstCode;
for (var j = start; j <= end; j++)
encoding[index++] = glyphs[j - firstCode - 1].unicode;
+
cmap.data = createCMapTable(glyphs);
}
}
From 1037fdf2ada515ee46c6f63fe4e9d8f7a4df0a28 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Mon, 4 Jul 2011 04:39:58 +0200
Subject: [PATCH 03/20] Fix a small issue with the 'name' table
---
fonts.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/fonts.js b/fonts.js
index 8bee706b2..dceda2cdd 100644
--- a/fonts.js
+++ b/fonts.js
@@ -988,7 +988,7 @@ var Font = (function Font() {
var nameTable =
"\x00\x00" + // format
string16(namesRecordCount) + // Number of names Record
- string16(namesRecordCount * 12 + 6); // Storage
+ string16(namesRecordCount * 12 + 6); // Offset to start of storage
// Build the name records field
var strOffset = 0;
@@ -1000,7 +1000,7 @@ var Font = (function Font() {
platforms[i] + // platform ID
encodings[i] + // encoding ID
languages[i] + // language ID
- string16(i) + // name ID
+ string16(j) + // name ID
string16(str.length) +
string16(strOffset);
nameTable += nameRecord;
@@ -1008,9 +1008,9 @@ var Font = (function Font() {
}
}
- nameTable += strings.join("") + stringsUnicode.join("");
+ nameTable += strings.join("") + stringsUnicode.join("");
return nameTable;
- }
+ };
function isFixedPitch(glyphs) {
for (var i = 0; i < glyphs.length - 1; i++) {
From 9b1d6a5e25571188a34b14d2d9a0b96c92051a2b Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Mon, 4 Jul 2011 06:07:49 +0200
Subject: [PATCH 04/20] Calculate the checksumAdjustement for the file
---
fonts.js | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/fonts.js b/fonts.js
index dceda2cdd..1964121c4 100644
--- a/fonts.js
+++ b/fonts.js
@@ -1024,14 +1024,14 @@ var Font = (function Font() {
// to write the table entry information about a table and another offset
// representing the offset where to draw the actual data of a particular
// table
- var kRequiredTablesCount = 9;
+ var tablesCount = 9;
var offsets = {
currentOffset: 0,
- virtualOffset: 9 * (4 * 4)
+ virtualOffset: tablesCount * (4 * 4)
};
var otf = new Uint8Array(kMaxFontFileSize);
- createOpenTypeHeader("\x4F\x54\x54\x4F", otf, offsets, 9);
+ createOpenTypeHeader("\x4F\x54\x54\x4F", otf, offsets, tablesCount);
var charstrings = font.charstrings;
properties.fixedPitch = isFixedPitch(charstrings);
@@ -1115,12 +1115,26 @@ var Font = (function Font() {
for (var field in fields)
createTableEntry(otf, offsets, field, fields[field]);
+ var headPosition = 0;
for (var field in fields) {
var table = fields[field];
+ if (field == "head")
+ headPosition = offsets.currentOffset;
+
otf.set(table, offsets.currentOffset);
offsets.currentOffset += table.length;
}
+ // Now calculate the checksumAdjustement for all the file and put it into
+ // head. This will make the head checksum incorrect but per spec that's
+ // the way it works.
+ var checksumAdjustement = 0;
+ for (var i = 0; i < offsets.currentOffset; i+=4)
+ checksumAdjustement += int16([otf[i], otf[i+1], otf[i+2], otf[i+3]]);
+ checksumAdjustement = 0xB1B0AFBA - checksumAdjustement;
+ otf.set(stringToArray(string32(checksumAdjustement)), headPosition + (2 * 4));
+
+
var fontData = [];
for (var i = 0; i < offsets.currentOffset; i++)
fontData.push(otf[i]);
From 8738b72f30f157392bcaf5c947f887fa22a8d6f8 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Mon, 4 Jul 2011 10:24:31 +0200
Subject: [PATCH 05/20] Use int32 instead of int16 for checksums
---
fonts.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fonts.js b/fonts.js
index 1964121c4..e61a8f666 100644
--- a/fonts.js
+++ b/fonts.js
@@ -541,7 +541,7 @@ var Font = (function Font() {
// checksum
var checksum = 0;
for (var i = 0; i < length; i+=4)
- checksum += int16([data[i], data[i+1], data[i+2], data[i+3]]);
+ checksum += int32([data[i], data[i+1], data[i+2], data[i+3]]);
var tableEntry = tag +
string32(checksum) +
From 2271f7df7fd31c2f15bfbcc4e24ff1a724995a44 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Wed, 6 Jul 2011 02:51:17 +0200
Subject: [PATCH 06/20] Fix some indentations issues
---
fonts.js | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/fonts.js b/fonts.js
index e61a8f666..5abc13fd3 100644
--- a/fonts.js
+++ b/fonts.js
@@ -643,17 +643,16 @@ var Font = (function Font() {
var ulUnicodeRange3 = 0;
var ulUnicodeRange4 = 0;
- var charset = properties.charset;
+ var charset = properties.charset;
if (charset && charset.length) {
- var firstCharIndex = null;
- var lastCharIndex = 0;
+ var firstCharIndex = null;
+ var lastCharIndex = 0;
- for (var i = 1; i < charset.length; i++) {
- var code = GlyphsUnicode[charset[i]];
- if (firstCharIndex > code || !firstCharIndex)
+ for (var i = 1; i < charset.length; i++) {var code = GlyphsUnicode[charset[i]];
+ if (firstCharIndex > code || !firstCharIndex)
firstCharIndex = code;
- if (lastCharIndex < code)
- lastCharIndex = code;
+ if (lastCharIndex < code)
+ lastCharIndex = code;
var position = getUnicodeRangeFor(code);
if (position < 32) {
From 10e96941350a83fccf31e49a6fe5a6cd814bded2 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Fri, 15 Jul 2011 14:58:14 +0200
Subject: [PATCH 07/20] Support font with characters below 0x20 declared in
format 1 cmap and be more general about the TrueType rewritting cases
---
fonts.js | 295 +++++++++++++++++++++++++++---------------------
web/viewer.html | 1 +
2 files changed, 165 insertions(+), 131 deletions(-)
diff --git a/fonts.js b/fonts.js
index 607e2aab9..b3961c8fc 100755
--- a/fonts.js
+++ b/fonts.js
@@ -372,7 +372,7 @@ function getUnicodeRangeFor(value) {
* var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
* type1Font.bind();
*/
-var Font = (function() {
+var Font = (function Font() {
var constructor = function font_constructor(name, file, properties) {
this.name = name;
this.textMatrix = properties.textMatrix || IDENTITY_MATRIX;
@@ -531,6 +531,19 @@ var Font = (function() {
}
ranges.push([start, end]);
}
+
+ // Removes duplicate ranges
+ for (var i = ranges.length - 1; i > 0; i--) {
+ var range = [];
+ var range1 = ranges[i];
+ var range2 = ranges[i - 1];
+ if (range1[0] == range2[1]) {
+ range2[0] = range2[0] - 1;
+ range2[1] = range1[1];
+ ranges.splice(i, 1);
+ }
+ }
+
return ranges;
};
@@ -790,21 +803,57 @@ var Font = (function() {
};
function replaceCMapTable(cmap, font, properties) {
- font.pos = (font.start ? font.start : 0) + cmap.length;
+ var start = (font.start ? font.start : 0) + cmap.length;
+ font.pos = start;
var version = int16(font.getBytes(2));
- var numTables = int16(font.getBytes(2));
+ var numRecords = int16(font.getBytes(2));
- for (var i = 0; i < numTables; i++) {
- var platformID = int16(font.getBytes(2));
- var encodingID = int16(font.getBytes(2));
- var offset = int32(font.getBytes(4));
+ var records = [];
+ for (var i = 0; i < numRecords; i++) {
+ records.push({
+ platformID: int16(font.getBytes(2)),
+ encodingID: int16(font.getBytes(2)),
+ offset: int32(font.getBytes(4))
+ });
+ };
+
+
+ for (var i = 0; i < numRecords; i++) {
+ var table = records[i];
+ font.pos = start + table.offset;
+
var format = int16(font.getBytes(2));
var length = int16(font.getBytes(2));
var language = int16(font.getBytes(2));
-
- if ((format == 0 && numTables == 1) ||
- (format == 6 && numTables == 1 && !properties.encoding.empty)) {
+
+ if (format == 0 && numRecords > 1) {
+ // Characters below 0x20 are controls characters that are hardcoded
+ // into the platform so if some characters in the font are assigned
+ // under this limit they will not be displayed so let's rewrite the
+ // CMap.
+ var map = [];
+ var rewrite = false;
+ for (var j = 0; j < 256; j++) {
+ var index = font.getByte();
+ if (index != 0) {
+ map.push(index);
+ if (j < 0x20)
+ rewrite = true;
+ }
+ }
+
+ if (rewrite) {
+ var glyphs = [];
+ for (var j = 0x20; j < 256; j++) {
+ // TODO do not hardcode WinAnsiEncoding
+ var unicode = GlyphsUnicode[Encodings["WinAnsiEncoding"][j]];
+ glyphs.push({ unicode: unicode });
+ }
+ cmap.data = createCMapTable(glyphs, true);
+ }
+ } else if ((format == 0 && numRecords == 1) ||
+ (format == 6 && numRecords == 1 && !properties.encoding.empty)) {
// Format 0 alone is not allowed by the sanitizer so let's rewrite
// that to a 3-1-4 Unicode BMP table
TODO('Use an other source of informations than ' +
@@ -818,7 +867,7 @@ var Font = (function() {
}
cmap.data = createCMapTable(glyphs);
- } else if (format == 6 && numTables == 1) {
+ } else if (format == 6 && numRecords == 1) {
// Format 6 is a 2-bytes dense mapping, which means the font data
// lives glue together even if they are pretty far in the unicode
// table. (This looks weird, so I can have missed something), this
@@ -871,10 +920,7 @@ var Font = (function() {
var header = readOpenTypeHeader(font);
var numTables = header.numTables;
- // This keep a reference to the CMap and the post tables since they can
- // be rewritted
- var cmap, post, nameTable, maxp;
-
+ var cmap, maxp;
var tables = [];
for (var i = 0; i < numTables; i++) {
var table = readTableEntry(font);
@@ -882,10 +928,6 @@ var Font = (function() {
if (index != -1) {
if (table.tag == 'cmap')
cmap = table;
- else if (table.tag == 'post')
- post = table;
- else if (table.tag == 'name')
- nameTable = table;
else if (table.tag == 'maxp')
maxp = table;
@@ -894,136 +936,127 @@ var Font = (function() {
tables.push(table);
}
- // If any tables are still in the array this means some required
- // tables are missing, which means that we need to rebuild the
- // font in order to pass the sanitizer.
- if (requiredTables.length && requiredTables[0] == 'OS/2') {
- // Create a new file to hold the new version of our truetype with a new
- // header and new offsets
- var ttf = new Uint8Array(kMaxFontFileSize);
+ // Create a new file to hold the new version of our truetype with a new
+ // header and new offsets
+ var ttf = new Uint8Array(kMaxFontFileSize);
- // The offsets object holds at the same time a representation of where
- // to write the table entry information about a table and another offset
- // representing the offset where to put the actual data of a particular
- // table
- var numTables = header.numTables + requiredTables.length;
- var offsets = {
- currentOffset: 0,
- virtualOffset: numTables * (4 * 4)
- };
+ // The offsets object holds at the same time a representation of where
+ // to write the table entry information about a table and another offset
+ // representing the offset where to put the actual data of a particular
+ // table
+ var numTables = header.numTables + requiredTables.length;
+ var offsets = {
+ currentOffset: 0,
+ virtualOffset: numTables * (4 * 4)
+ };
- // The new numbers of tables will be the last one plus the num
- // of missing tables
- createOpenTypeHeader('\x00\x01\x00\x00', ttf, offsets, numTables);
+ // The new numbers of tables will be the last one plus the num
+ // of missing tables
+ createOpenTypeHeader('\x00\x01\x00\x00', ttf, offsets, numTables);
- // Insert the missing table
+ if (requiredTables.indexOf('OS/2') != -1) {
tables.push({
tag: 'OS/2',
data: stringToArray(createOS2Table(properties))
});
+ }
- // Replace the old CMAP table with a shiny new one
- if (properties.type == 'CIDFontType2') {
- // Type2 composite fonts map characters directly to glyphs so the cmap
- // table must be replaced.
+ // Replace the old CMAP table with a shiny new one
+ if (properties.type == 'CIDFontType2') {
+ // Type2 composite fonts map characters directly to glyphs so the cmap
+ // table must be replaced.
- var glyphs = [];
- var charset = properties.charset;
- if (!charset.length) {
- // PDF did not contain a GIDMap for the font so create an identity cmap
+ var glyphs = [];
+ var charset = properties.charset;
+ if (!charset.length) {
+ // PDF did not contain a GIDMap for the font so create an identity cmap
- // First get the number of glyphs from the maxp table
- font.pos = (font.start ? font.start : 0) + maxp.length;
- var version = int16(font.getBytes(4));
- var numGlyphs = int16(font.getBytes(2));
+ // First get the number of glyphs from the maxp table
+ font.pos = (font.start ? font.start : 0) + maxp.length;
+ var version = int16(font.getBytes(4));
+ var numGlyphs = int16(font.getBytes(2));
- // Now create an identity mapping
- for (var i = 1; i < numGlyphs; i++) {
- glyphs.push({
- unicode: i
- });
- }
- } else {
- for (var i = 1; i < charset.length; i++) {
- var index = charset.indexOf(i);
- if (index != -1) {
- glyphs.push({
- unicode: index
- });
- } else {
- break;
- }
- }
- }
-
- if (!cmap) {
- // Font did not contain a cmap
- tables.push({
- tag: 'cmap',
- data: createCMapTable(glyphs)
- })
- } else {
- cmap.data = createCMapTable(glyphs);
+ // Now create an identity mapping
+ for (var i = 1; i < numGlyphs; i++) {
+ glyphs.push({
+ unicode: i
+ });
}
} else {
- replaceCMapTable(cmap, font, properties);
+ for (var i = 1; i < charset.length; i++) {
+ var index = charset.indexOf(i);
+ if (index != -1) {
+ glyphs.push({
+ unicode: index
+ });
+ } else {
+ break;
+ }
+ }
}
-
- // Rewrite the 'post' table if needed
- if (!post) {
+
+ if (!cmap) {
+ // Font did not contain a cmap
tables.push({
- tag: 'post',
- data: stringToArray(createPostTable(properties))
- });
+ tag: 'cmap',
+ data: createCMapTable(glyphs)
+ })
+ } else {
+ cmap.data = createCMapTable(glyphs);
}
-
- // Rewrite the 'name' table if needed
- if (!nameTable) {
- tables.push({
- tag: 'name',
- data: stringToArray(createNameTable(this.name))
- });
- }
-
- // Tables needs to be written by ascendant alphabetic order
- tables.sort(function tables_sort(a, b) {
- return (a.tag > b.tag) - (a.tag < b.tag);
- });
-
- // rewrite the tables but tweak offsets
- for (var i = 0; i < tables.length; i++) {
- var table = tables[i];
- var data = [];
-
- var tableData = table.data;
- for (var j = 0; j < tableData.length; j++)
- data.push(tableData[j]);
- createTableEntry(ttf, offsets, table.tag, data);
- }
-
- // Add the table datas
- for (var i = 0; i < tables.length; i++) {
- var table = tables[i];
- var tableData = table.data;
- ttf.set(tableData, offsets.currentOffset);
- offsets.currentOffset += tableData.length;
-
- // 4-byte aligned data
- while (offsets.currentOffset & 3)
- offsets.currentOffset++;
- }
-
- var fontData = [];
- for (var i = 0; i < offsets.currentOffset; i++)
- fontData.push(ttf[i]);
-
- return fontData;
- } else if (requiredTables.length) {
- error('Table ' + requiredTables[0] +
- ' is missing from the TrueType font');
+ } else {
+ replaceCMapTable(cmap, font, properties);
}
- return font.getBytes();
+ // Rewrite the 'post' table if needed
+ if (requiredTables.indexOf('post') != -1) {
+ tables.push({
+ tag: 'post',
+ data: stringToArray(createPostTable(properties))
+ });
+ }
+
+ // Rewrite the 'name' table if needed
+ if (requiredTables.indexOf('name') != -1) {
+ tables.push({
+ tag: 'name',
+ data: stringToArray(createNameTable(this.name))
+ });
+ }
+
+ // Tables needs to be written by ascendant alphabetic order
+ tables.sort(function tables_sort(a, b) {
+ return (a.tag > b.tag) - (a.tag < b.tag);
+ });
+
+ // rewrite the tables but tweak offsets
+ for (var i = 0; i < tables.length; i++) {
+ var table = tables[i];
+ var data = [];
+
+ var tableData = table.data;
+ for (var j = 0; j < tableData.length; j++)
+ data.push(tableData[j]);
+ createTableEntry(ttf, offsets, table.tag, data);
+ }
+
+ // Add the table datas
+ for (var i = 0; i < tables.length; i++) {
+ var table = tables[i];
+ var tableData = table.data;
+ ttf.set(tableData, offsets.currentOffset);
+ offsets.currentOffset += tableData.length;
+
+ // 4-byte aligned data
+ while (offsets.currentOffset & 3)
+ offsets.currentOffset++;
+ }
+
+ var fontData = [];
+ for (var i = 0; i < offsets.currentOffset; i++)
+ fontData.push(ttf[i]);
+
+ return fontData;
},
convert: function font_convert(fontName, font, properties) {
diff --git a/web/viewer.html b/web/viewer.html
index df9604db4..8caa40f3e 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -8,6 +8,7 @@
+
From b8fc365fffac342f99a155d6082630a0cfdcb1a8 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Fri, 15 Jul 2011 15:41:30 +0200
Subject: [PATCH 08/20] Fix the ranges duplication cleanup features
---
fonts.js | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/fonts.js b/fonts.js
index b3961c8fc..4eb9406ed 100755
--- a/fonts.js
+++ b/fonts.js
@@ -534,13 +534,11 @@ var Font = (function Font() {
// Removes duplicate ranges
for (var i = ranges.length - 1; i > 0; i--) {
- var range = [];
- var range1 = ranges[i];
- var range2 = ranges[i - 1];
- if (range1[0] == range2[1]) {
- range2[0] = range2[0] - 1;
- range2[1] = range1[1];
- ranges.splice(i, 1);
+ var range = ranges[i];
+ var prevRange = ranges[i - 1];
+ if (range[0] <= prevRange[1]) {
+ range[0] = prevRange[0] - 2;
+ ranges.splice(i - 1, 1);
}
}
@@ -850,7 +848,7 @@ var Font = (function Font() {
var unicode = GlyphsUnicode[Encodings["WinAnsiEncoding"][j]];
glyphs.push({ unicode: unicode });
}
- cmap.data = createCMapTable(glyphs, true);
+ cmap.data = createCMapTable(glyphs);
}
} else if ((format == 0 && numRecords == 1) ||
(format == 6 && numRecords == 1 && !properties.encoding.empty)) {
From e2d808a60f88c69b20ea9c8e8fba38d62922ed15 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Fri, 15 Jul 2011 16:02:32 +0200
Subject: [PATCH 09/20] Switch length versus offset mistake in readTableEntry
---
fonts.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/fonts.js b/fonts.js
index 4eb9406ed..eb3b25d50 100755
--- a/fonts.js
+++ b/fonts.js
@@ -784,8 +784,8 @@ var Font = (function Font() {
return {
tag: tag,
checksum: checksum,
- length: offset,
- offset: length,
+ length: length,
+ offset: offset,
data: data
};
};
@@ -801,7 +801,7 @@ var Font = (function Font() {
};
function replaceCMapTable(cmap, font, properties) {
- var start = (font.start ? font.start : 0) + cmap.length;
+ var start = (font.start ? font.start : 0) + cmap.offset;
font.pos = start;
var version = int16(font.getBytes(2));
@@ -970,7 +970,7 @@ var Font = (function Font() {
// PDF did not contain a GIDMap for the font so create an identity cmap
// First get the number of glyphs from the maxp table
- font.pos = (font.start ? font.start : 0) + maxp.length;
+ font.pos = (font.start ? font.start : 0) + maxp.offset;
var version = int16(font.getBytes(4));
var numGlyphs = int16(font.getBytes(2));
From aea63a70519113811a92b1d72d31692fb924928f Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Fri, 15 Jul 2011 16:22:45 +0200
Subject: [PATCH 10/20] Fix missing sidebearings from the hmtx table (see
canvas.pdf)
---
fonts.js | 77 ++++++++++++++++++++++++++++++++++----------------------
1 file changed, 47 insertions(+), 30 deletions(-)
diff --git a/fonts.js b/fonts.js
index eb3b25d50..ac8da119d 100755
--- a/fonts.js
+++ b/fonts.js
@@ -816,7 +816,6 @@ var Font = (function Font() {
});
};
-
for (var i = 0; i < numRecords; i++) {
var table = records[i];
font.pos = start + table.offset;
@@ -824,7 +823,7 @@ var Font = (function Font() {
var format = int16(font.getBytes(2));
var length = int16(font.getBytes(2));
var language = int16(font.getBytes(2));
-
+
if (format == 0 && numRecords > 1) {
// Characters below 0x20 are controls characters that are hardcoded
// into the platform so if some characters in the font are assigned
@@ -840,7 +839,7 @@ var Font = (function Font() {
rewrite = true;
}
}
-
+
if (rewrite) {
var glyphs = [];
for (var j = 0x20; j < 256; j++) {
@@ -918,7 +917,7 @@ var Font = (function Font() {
var header = readOpenTypeHeader(font);
var numTables = header.numTables;
- var cmap, maxp;
+ var cmap, maxp, hhea, hmtx;
var tables = [];
for (var i = 0; i < numTables; i++) {
var table = readTableEntry(font);
@@ -928,6 +927,10 @@ var Font = (function Font() {
cmap = table;
else if (table.tag == 'maxp')
maxp = table;
+ else if (table.tag == 'hhea')
+ hhea = table;
+ else if (table.tag == 'hmtx')
+ hmtx = table;
requiredTables.splice(index, 1);
}
@@ -944,7 +947,7 @@ var Font = (function Font() {
// table
var numTables = header.numTables + requiredTables.length;
var offsets = {
- currentOffset: 0,
+ currentOffset: 0,
virtualOffset: numTables * (4 * 4)
};
@@ -952,29 +955,45 @@ var Font = (function Font() {
// of missing tables
createOpenTypeHeader('\x00\x01\x00\x00', ttf, offsets, numTables);
- if (requiredTables.indexOf('OS/2') != -1) {
+ if (requiredTables.indexOf('OS/2') != -1) {
tables.push({
tag: 'OS/2',
data: stringToArray(createOS2Table(properties))
});
- }
+ }
+
+ // Ensure the hmtx tables contains an advance width and a sidebearing
+ // for the number of glyphs declared in the maxp table
+ font.pos = (font.start ? font.start : 0) + maxp.offset;
+ var version = int16(font.getBytes(4));
+ var numGlyphs = int16(font.getBytes(2));
+
+ font.pos = (font.start ? font.start : 0) + hhea.offset;
+ font.pos += hhea.length - 2;
+ var numOfHMetrics = int16(font.getBytes(2));
+
+ var numOfSidebearings = numGlyphs - numOfHMetrics;
+ var numMissing = numOfSidebearings - (hmtx.length - numOfHMetrics * 4);
+ if (numMissing > 0) {
+ font.pos = (font.start ? font.start : 0) + hmtx.offset;
+ var metrics = "";
+ for (var i = 0; i < hmtx.length; i++)
+ metrics += String.fromCharCode(font.getByte());
+ for (var i = 0; i < numMissing; i++)
+ metrics += "\x00\x00";
+ hmtx.data = stringToArray(metrics);
+ }
+
// Replace the old CMAP table with a shiny new one
if (properties.type == 'CIDFontType2') {
- // Type2 composite fonts map characters directly to glyphs so the cmap
+ // Type2 composite fonts map characters directly to glyphs so the cmap
// table must be replaced.
var glyphs = [];
var charset = properties.charset;
if (!charset.length) {
- // PDF did not contain a GIDMap for the font so create an identity cmap
-
- // First get the number of glyphs from the maxp table
- font.pos = (font.start ? font.start : 0) + maxp.offset;
- var version = int16(font.getBytes(4));
- var numGlyphs = int16(font.getBytes(2));
-
- // Now create an identity mapping
+ // Type2 composite fonts map characters directly to glyphs so the cmap
for (var i = 1; i < numGlyphs; i++) {
glyphs.push({
unicode: i
@@ -983,27 +1002,25 @@ var Font = (function Font() {
} else {
for (var i = 1; i < charset.length; i++) {
var index = charset.indexOf(i);
- if (index != -1) {
- glyphs.push({
- unicode: index
- });
- } else {
+ if (index == -1)
break;
- }
+
+ glyphs.push({
+ unicode: index
+ });
}
}
-
+
if (!cmap) {
- // Font did not contain a cmap
- tables.push({
+ cmap = {
tag: 'cmap',
- data: createCMapTable(glyphs)
- })
- } else {
- cmap.data = createCMapTable(glyphs);
+ data: null
+ };
+ tables.push(cmap);
}
+ cmap.data = createCMapTable(glyphs);
} else {
- replaceCMapTable(cmap, font, properties);
+ replaceCMapTable(cmap, font, properties);
}
// Rewrite the 'post' table if needed
From 42653edf9a47e281ddbf210d2723e69884a79807 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Fri, 15 Jul 2011 19:14:07 +0200
Subject: [PATCH 11/20] Add support for beginfbchar
---
fonts.js | 38 +++++++++++++++++++++-----------------
pdf.js | 14 ++++++++------
2 files changed, 29 insertions(+), 23 deletions(-)
diff --git a/fonts.js b/fonts.js
index ac8da119d..a54168a1e 100755
--- a/fonts.js
+++ b/fonts.js
@@ -816,6 +816,8 @@ var Font = (function Font() {
});
};
+ var encoding = properties.encoding;
+ var charset = properties.charset;
for (var i = 0; i < numRecords; i++) {
var table = records[i];
font.pos = start + table.offset;
@@ -824,38 +826,41 @@ var Font = (function Font() {
var length = int16(font.getBytes(2));
var language = int16(font.getBytes(2));
- if (format == 0 && numRecords > 1) {
+ if (format == 0) {
// Characters below 0x20 are controls characters that are hardcoded
// into the platform so if some characters in the font are assigned
// under this limit they will not be displayed so let's rewrite the
// CMap.
- var map = [];
- var rewrite = false;
- for (var j = 0; j < 256; j++) {
- var index = font.getByte();
- if (index != 0) {
- map.push(index);
- if (j < 0x20)
- rewrite = true;
+ var glyphs = [];
+ if (encoding.empty) {
+ var orderedGlyphs= [];
+ for ( var j = 0; j < charset.length; j++) {
+ var unicode = GlyphsUnicode[charset[font.getByte()]] || 0;
+ glyphs.push({ unicode: unicode });
+ orderedGlyphs.push(unicode);
}
- }
- if (rewrite) {
- var glyphs = [];
+ orderedGlyphs.sort(function(a, b) {
+ return a - b;
+ });
+
+ for (var p in encoding) {
+ if (p != "empty")
+ properties.encoding[p] = orderedGlyphs[p - 1];
+ }
+ } else {
for (var j = 0x20; j < 256; j++) {
// TODO do not hardcode WinAnsiEncoding
var unicode = GlyphsUnicode[Encodings["WinAnsiEncoding"][j]];
glyphs.push({ unicode: unicode });
}
- cmap.data = createCMapTable(glyphs);
}
- } else if ((format == 0 && numRecords == 1) ||
- (format == 6 && numRecords == 1 && !properties.encoding.empty)) {
+ cmap.data = createCMapTable(glyphs);
+ } else if (format == 6 && numRecords == 1 && !encoding.empty) {
// Format 0 alone is not allowed by the sanitizer so let's rewrite
// that to a 3-1-4 Unicode BMP table
TODO('Use an other source of informations than ' +
'charset here, it is not reliable');
- var charset = properties.charset;
var glyphs = [];
for (var j = 0; j < charset.length; j++) {
glyphs.push({
@@ -898,7 +903,6 @@ var Font = (function Font() {
assert(ranges.length == 1, 'Got ' + ranges.length +
' ranges in a dense array');
- var encoding = properties.encoding;
var denseRange = ranges[0];
var start = denseRange[0];
var end = denseRange[1];
diff --git a/pdf.js b/pdf.js
index a3179406c..19d7dbece 100644
--- a/pdf.js
+++ b/pdf.js
@@ -3763,6 +3763,7 @@ var PartialEvaluator = (function() {
error('useCMap is not implemented');
break;
+ case 'beginbfchar':
case 'beginbfrange':
case 'begincodespacerange':
token = '';
@@ -3780,17 +3781,18 @@ var PartialEvaluator = (function() {
var code = parseInt('0x' + tokens[j + 2]);
for (var k = startRange; k <= endRange; k++) {
- // The encoding mapping table will be filled
- // later during the building phase
- //encodingMap[k] = GlyphsUnicode[encoding[code]];
charset.push(encoding[code++] || '.notdef');
}
}
break;
- case 'beginfbchar':
- case 'endfbchar':
- error('fbchar parsing is not implemented');
+ case 'endbfchar':
+ for (var j = 0; j < tokens.length; j += 2) {
+ var index = parseInt('0x' + tokens[j]);
+ var code = parseInt('0x' + tokens[j + 1]);
+ encodingMap[index] = GlyphsUnicode[encoding[code]];
+ charset.push(encoding[code] || '.notdef');
+ }
break;
default:
From c6c72291d99524383debf4b71f5a945792f3a6d2 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Tue, 19 Jul 2011 14:22:51 +0200
Subject: [PATCH 12/20] Do not rasterize below 14px
---
fonts.js | 3 ++-
pdf.js | 9 ++++++++-
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/fonts.js b/fonts.js
index a54168a1e..edd54b0a1 100755
--- a/fonts.js
+++ b/fonts.js
@@ -22,7 +22,7 @@ var kMaxWaitForFontFace = 1000;
*/
var Fonts = (function Fonts() {
- var kScalePrecision = 40;
+ var kScalePrecision = 50;
var fonts = [];
if (!isWorker) {
@@ -404,6 +404,7 @@ var Font = (function Font() {
// Repair the TrueType file if it is can be damaged in the point of
// view of the sanitizer
data = this.checkAndRepair(name, file, properties);
+ writeToFile(data, "/tmp/file." + this.name + ".ttf");
break;
default:
diff --git a/pdf.js b/pdf.js
index f164dbd68..03cb16126 100644
--- a/pdf.js
+++ b/pdf.js
@@ -3898,6 +3898,9 @@ function ScratchCanvas(width, height) {
}
var CanvasGraphics = (function() {
+ var kScalePrecision = 50;
+ var kRasterizerMin = 14;
+
function constructor(canvasCtx, imageCanvas) {
this.ctx = canvasCtx;
this.current = new CanvasExtraState();
@@ -4113,8 +4116,10 @@ var CanvasGraphics = (function() {
if (this.ctx.$setFont) {
this.ctx.$setFont(fontName, size);
} else {
- this.ctx.font = size + 'px "' + fontName + '"';
Fonts.setActive(fontName, fontObj, size);
+
+ size = (size <= kRasterizerMin) ? size * kScalePrecision : size;
+ this.ctx.font = size + 'px "' + fontName + '"';
}
},
setTextRenderingMode: function(mode) {
@@ -4162,6 +4167,8 @@ var CanvasGraphics = (function() {
ctx.translate(current.x, -1 * current.y);
var font = this.current.font;
if (font) {
+ if (this.current.fontSize < kRasterizerMin)
+ ctx.transform(1 / kScalePrecision, 0, 0, 1 / kScalePrecision, 0, 0);
ctx.transform.apply(ctx, font.textMatrix);
text = font.charsToUnicode(text);
}
From 913504a9378b69dbb52f75729914ca9e615f8f24 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Tue, 19 Jul 2011 14:23:57 +0200
Subject: [PATCH 13/20] Remover leftover
---
fonts.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/fonts.js b/fonts.js
index edd54b0a1..9a064f4c5 100755
--- a/fonts.js
+++ b/fonts.js
@@ -404,7 +404,6 @@ var Font = (function Font() {
// Repair the TrueType file if it is can be damaged in the point of
// view of the sanitizer
data = this.checkAndRepair(name, file, properties);
- writeToFile(data, "/tmp/file." + this.name + ".ttf");
break;
default:
From 776c10d4e61fb8ce5103c235afaba4becdd66975 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Tue, 19 Jul 2011 14:29:05 +0200
Subject: [PATCH 14/20] Fix a regression on the application of the textMatrix
extracted from a CFF font
---
fonts.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fonts.js b/fonts.js
index 9a064f4c5..d08d43a7c 100755
--- a/fonts.js
+++ b/fonts.js
@@ -375,7 +375,6 @@ function getUnicodeRangeFor(value) {
var Font = (function Font() {
var constructor = function font_constructor(name, file, properties) {
this.name = name;
- this.textMatrix = properties.textMatrix || IDENTITY_MATRIX;
this.encoding = properties.encoding;
// If the font is to be ignored, register it like an already loaded font
@@ -411,6 +410,7 @@ var Font = (function Font() {
break;
}
this.data = data;
+ this.textMatrix = properties.textMatrix || IDENTITY_MATRIX;
this.type = properties.type;
this.id = Fonts.registerFont(name, data, properties);
this.loadedName = 'pdfFont' + this.id;
From 6600e747e5e48a6acff3d8d140ac6d478f977327 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Tue, 19 Jul 2011 15:04:22 +0200
Subject: [PATCH 15/20] Fix next line since we already invert the position of
the viewport by doing a negative scale
---
pdf.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pdf.js b/pdf.js
index 03cb16126..63a948df1 100644
--- a/pdf.js
+++ b/pdf.js
@@ -4136,7 +4136,7 @@ var CanvasGraphics = (function() {
}
},
setLeadingMoveText: function(x, y) {
- this.setLeading(-y);
+ this.setLeading(y);
this.moveText(x, y);
},
setTextMatrix: function(a, b, c, d, e, f) {
From 4275a68e2982840c201e3a5a43839603ca034d13 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Tue, 19 Jul 2011 16:52:29 +0200
Subject: [PATCH 16/20] Filter more characters on font name
---
pdf.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pdf.js b/pdf.js
index 63a948df1..33e554310 100644
--- a/pdf.js
+++ b/pdf.js
@@ -3674,7 +3674,7 @@ var PartialEvaluator = (function() {
var fontName = descriptor.get('FontName');
assertWellFormed(IsName(fontName), 'invalid font name');
- fontName = fontName.name.replace('+', '_');
+ fontName = fontName.name.replace(/[\+,\-]/g, '_');
var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
if (!fontFile)
From 3cc9912acd970ed10593dd1e957ccb0d52c0985f Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Wed, 20 Jul 2011 14:29:07 +0200
Subject: [PATCH 17/20] Add a simpler path for cmap format 0 to cmap format 4
---
fonts.js | 47 ++++++++++++++++-------------------------------
pdf.js | 3 +--
2 files changed, 17 insertions(+), 33 deletions(-)
diff --git a/fonts.js b/fonts.js
index d08d43a7c..44f81442c 100755
--- a/fonts.js
+++ b/fonts.js
@@ -533,6 +533,7 @@ var Font = (function Font() {
}
// Removes duplicate ranges
+/*
for (var i = ranges.length - 1; i > 0; i--) {
var range = ranges[i];
var prevRange = ranges[i - 1];
@@ -541,12 +542,12 @@ var Font = (function Font() {
ranges.splice(i - 1, 1);
}
}
+*/
return ranges;
};
- function createCMapTable(glyphs) {
- glyphs.push({ unicode: 0x0000 });
+ function createCMapTable(glyphs, deltas) {
var ranges = getRanges(glyphs);
var numTables = 1;
@@ -573,19 +574,18 @@ var Font = (function Font() {
var range = ranges[i];
var start = range[0];
var end = range[1];
- var delta = (bias - start) & 0xffff;
+ var offset = (segCount - i) * 2 + bias * 2;
bias += (end - start + 1);
startCount += string16(start);
endCount += string16(end);
- idDeltas += string16(delta);
- idRangeOffsets += string16(0);
-
- for (var j = start; j <= end; j++) {
- glyphsIds += string16(j);
- }
+ idDeltas += string16(0);
+ idRangeOffsets += string16(offset);
}
+ for (var i = 0; i < glyphs.length; i++)
+ glyphsIds += string16(deltas ? deltas[i] : i + 1);
+
endCount += '\xFF\xFF';
startCount += '\xFF\xFF';
idDeltas += '\x00\x01';
@@ -832,30 +832,15 @@ var Font = (function Font() {
// under this limit they will not be displayed so let's rewrite the
// CMap.
var glyphs = [];
- if (encoding.empty) {
- var orderedGlyphs= [];
- for ( var j = 0; j < charset.length; j++) {
- var unicode = GlyphsUnicode[charset[font.getByte()]] || 0;
- glyphs.push({ unicode: unicode });
- orderedGlyphs.push(unicode);
- }
-
- orderedGlyphs.sort(function(a, b) {
- return a - b;
- });
-
- for (var p in encoding) {
- if (p != "empty")
- properties.encoding[p] = orderedGlyphs[p - 1];
- }
- } else {
- for (var j = 0x20; j < 256; j++) {
- // TODO do not hardcode WinAnsiEncoding
- var unicode = GlyphsUnicode[Encodings["WinAnsiEncoding"][j]];
- glyphs.push({ unicode: unicode });
+ var deltas = [];
+ for (var j = 0; j < 256; j++) {
+ var index = font.getByte();
+ if (index) {
+ deltas.push(index);
+ glyphs.push({ unicode : j });
}
}
- cmap.data = createCMapTable(glyphs);
+ cmap.data = createCMapTable(glyphs, deltas);
} else if (format == 6 && numRecords == 1 && !encoding.empty) {
// Format 0 alone is not allowed by the sanitizer so let's rewrite
// that to a 3-1-4 Unicode BMP table
diff --git a/pdf.js b/pdf.js
index 33e554310..62e9dac4f 100644
--- a/pdf.js
+++ b/pdf.js
@@ -3722,9 +3722,8 @@ var PartialEvaluator = (function() {
var baseName = encoding.get('BaseEncoding');
if (baseName) {
var base = Encodings[baseName.name];
- var index = 0;
for (var j = 0, end = base.length; j < end; j++)
- encodingMap[index++] = GlyphsUnicode[base[j]];
+ encodingMap[j] = GlyphsUnicode[base[j]] || 0;
} else {
TODO('need to load default encoding');
}
From 6311977fee60f3b6e5ef492db59206b02e271583 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Wed, 20 Jul 2011 15:18:44 +0200
Subject: [PATCH 18/20] Merge with upstream
---
fonts.js | 27 +++++++++++++++------------
pdf.js | 6 +++++-
2 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/fonts.js b/fonts.js
index 44f81442c..8770c8d06 100755
--- a/fonts.js
+++ b/fonts.js
@@ -532,18 +532,6 @@ var Font = (function Font() {
ranges.push([start, end]);
}
- // Removes duplicate ranges
-/*
- for (var i = ranges.length - 1; i > 0; i--) {
- var range = ranges[i];
- var prevRange = ranges[i - 1];
- if (range[0] <= prevRange[1]) {
- range[0] = prevRange[0] - 2;
- ranges.splice(i - 1, 1);
- }
- }
-*/
-
return ranges;
};
@@ -840,6 +828,21 @@ var Font = (function Font() {
glyphs.push({ unicode : j });
}
}
+
+ var rewrite = false;
+ for (var code in encoding) {
+ if (code < 0x20 && encoding[code])
+ rewrite = true;
+
+ if (rewrite)
+ encoding[code] = parseInt(code) + 0x1F;
+ }
+
+ if (rewrite) {
+ for (var j = 0; j < glyphs.length; j++) {
+ glyphs[j].unicode += 0x1F;
+ }
+ }
cmap.data = createCMapTable(glyphs, deltas);
} else if (format == 6 && numRecords == 1 && !encoding.empty) {
// Format 0 alone is not allowed by the sanitizer so let's rewrite
diff --git a/pdf.js b/pdf.js
index 62e9dac4f..32779f5d1 100644
--- a/pdf.js
+++ b/pdf.js
@@ -3733,7 +3733,11 @@ var PartialEvaluator = (function() {
var index = 0;
for (var j = 0; j < differences.length; j++) {
var data = differences[j];
- IsNum(data) ? index = data : encodingMap[index++] = data;
+ if (subType.name == 'TrueType') {
+ IsNum(data) ? index = data : encodingMap[index++] = j;
+ } else {
+ IsNum(data) ? index = data : encodingMap[index++] = GlyphsUnicode[data.name];
+ }
}
// Get the font charset if any
From 1d59de6c12f1a75455a087d98fd4f7e4f256f706 Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Thu, 21 Jul 2011 11:01:38 +0200
Subject: [PATCH 19/20] Fix a > 32000 conversion error in type1 to type2
charstring
---
fonts.js | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/fonts.js b/fonts.js
index 8770c8d06..5a64a645a 100755
--- a/fonts.js
+++ b/fonts.js
@@ -1786,8 +1786,10 @@ CFF.prototype = {
String.fromCharCode((value >> 8) & 0xFF) +
String.fromCharCode(value & 0xFF);
} else if (value >= (-2147483648) && value <= 2147483647) {
+ value ^= 0xffffffff;
+ value += 1;
return '\xff' +
- String.fromCharCode((value >>> 24) & 0xFF) +
+ String.fromCharCode((value >> 24) & 0xFF) +
String.fromCharCode((value >> 16) & 0xFF) +
String.fromCharCode((value >> 8) & 0xFF) +
String.fromCharCode(value & 0xFF);
@@ -1893,7 +1895,14 @@ CFF.prototype = {
charstring[i] = cmd;
}
} else {
- charstring.splice(i, 1, 28, command >> 8, command & 0xff);
+ // Type1 charstring use a division for number above 32000
+ if (command > 32000) {
+ var divisor = charstring[i + 1];
+ command /= divisor;
+ charstring.splice(i, 3, 28, command >> 8, command & 0xff);
+ } else {
+ charstring.splice(i, 1, 28, command >> 8, command & 0xff);
+ }
i += 2;
}
}
From f5b9a9355b982b7ac76ac954b3a8086cfd6e468a Mon Sep 17 00:00:00 2001
From: Vivien Nicolas <21@vingtetun.org>
Date: Thu, 21 Jul 2011 20:14:50 +0200
Subject: [PATCH 20/20] Get rid of the inclusion of fonts_utils
---
web/viewer.html | 1 -
1 file changed, 1 deletion(-)
diff --git a/web/viewer.html b/web/viewer.html
index 8caa40f3e..df9604db4 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -8,7 +8,6 @@
-