From bcf5ade41c209246ebefc74ef7fad011b2a4b896 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Sun, 26 Jun 2011 10:04:56 +0200 Subject: [PATCH 01/12] Kill Flatten - part 1 --- fonts.js | 103 +++++++++++++++++++++++++------------------------------ 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/fonts.js b/fonts.js index 6ac582b18..f922c79ed 100644 --- a/fonts.js +++ b/fonts.js @@ -980,16 +980,8 @@ var Type1Parser = function() { "12": "div", // callothersubr is a mechanism to make calls on the postscript - // interpreter. - // TODO When decodeCharstring encounter such a command it should - // directly do: - // - pop the previous charstring[] command into 'index' - // - pop the previous charstring[] command and ignore it, it is - // normally the number of element to push on the stack before - // the command but since everything will be pushed on the stack - // by the PS interpreter when it will read them that is safe to - // ignore this command - // - push the content of the OtherSubrs[index] inside charstring[] + // interpreter, this is not supported by Type2 charstring but hopefully + // most of the default commands can be ignored safely. "16": "callothersubr", "17": "pop", @@ -1009,9 +1001,12 @@ var Type1Parser = function() { "31": "hvcurveto" }; - function decodeCharString(array) { - var charString = []; + var kEscapeCommand = 12; + function decodeCharString(array) { + var charstring = []; + + var z = 0; var value = ""; var count = array.length; for (var i = 0; i < count; i++) { @@ -1019,10 +1014,44 @@ var Type1Parser = function() { if (value < 32) { var command = null; - if (value == 12) { + if (value == kEscapeCommand) { var escape = array[++i]; + + // TODO Clean this code + if (escape == 16) { + var index = charstring.pop(); + var argc = charstring.pop(); + var data = charstring.pop(); + + // If the flex mechanishm is not used in a font program, Adobe + // state that that entries 0, 1 and 2 can simply be replace by + // {}, which means that we can simply ignore them. + if (index < 3) { + continue; + } + + // This is the same things about hint replacement, if it is not used + // entry 3 can be replaced by {3} + if (index == 3) { + charstring.push(3); + i++; + continue; + } + } + command = charStringDictionary["12"][escape]; } else { + + // TODO Clean this code + if (value == 13) { + var charWidthVector = charstring[1]; + var leftSidebearing = charstring[0]; + + charstring.push(leftSidebearing, "hmoveto"); + charstring.splice(0, 1); + continue; + } + command = charStringDictionary[value]; } @@ -1044,16 +1073,14 @@ var Type1Parser = function() { } else if (value <= 254) { value = -((value - 251) * 256) - parseInt(array[++i]) - 108; } else { - var byte = array[++i]; - var high = (byte >> 1); - value = (byte - high) << 24 | array[++i] << 16 | - array[++i] << 8 | array[++i]; + value = (array[++i] & 0xff) << 24 | (array[++i] & 0xff) << 16 | + (array[++i] & 0xff) << 8 | (array[++i] & 0xff) << 0; } - charString.push(value); + charstring.push(value); } - return charString; + return charstring; }; /** @@ -1305,46 +1332,8 @@ CFF.prototype = { var i = 0; while (true) { var obj = charstring[i]; - if (obj == null) - return []; - if (obj.charAt) { switch (obj) { - case "callothersubr": - var index = charstring[i - 1]; - var count = charstring[i - 2]; - var data = charstring[i - 3]; - - // If the flex mechanishm is not used in a font program, Adobe - // state that that entries 0, 1 and 2 can simply be replace by - // {}, which means that we can simply ignore them. - if (index < 3) { - i -= 3; - continue; - } - - // This is the same things about hint replacment, if it is not used - // entry 3 can be replaced by {} - if (index == 3) { - if (!data) { - charstring.splice(i - 2, 4, 3); - i -= 3; - } else { - // 5 to remove the arguments, the callothersubr call and the pop command - charstring.splice(i - 3, 5, 3); - i -= 3; - } - } - break; - - case "hsbw": - var charWidthVector = charstring[1]; - var leftSidebearing = charstring[0]; - - charstring.splice(i, 1, leftSidebearing, "hmoveto"); - charstring.splice(0, 1); - break; - case "endchar": case "return": // CharString is ready to be re-encode to commands number at this point From 798d7a10cae0995413662f3308d724e52557f71c Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Mon, 27 Jun 2011 21:17:25 +0200 Subject: [PATCH 02/12] Use the right width field in hmtx --- fonts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index f922c79ed..a3645cd43 100644 --- a/fonts.js +++ b/fonts.js @@ -733,7 +733,7 @@ var Font = (function () { hmtx = "\x01\xF4\x00\x00"; // Fake .notdef var width = 0, lsb = 0; for (var i = 0; i < charstrings.length; i++) { - width = charstrings[i].charstring[1]; + width = charstrings[i].charstring[0]; hmtx += string16(width) + string16(lsb); } hmtx = stringToArray(hmtx); From 61da963dae54ea60d4b1d4e9057fc42adae1d511 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 28 Jun 2011 00:11:53 +0200 Subject: [PATCH 03/12] Give a shot at passing better information to hmtx (hinting is slightly broken) --- fonts.js | 63 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/fonts.js b/fonts.js index a3645cd43..fe42cbcc3 100644 --- a/fonts.js +++ b/fonts.js @@ -182,7 +182,16 @@ var Font = (function () { return array; }; - function string16(value) { + function string16(value, signed) { + if (signed && value < 0) { + value = Math.abs(value); + var byte = (value >> 8) & 0xff; + return String.fromCharCode(byte ^ 0xff) + + String.fromCharCode(value & 0xff); + } else if (signed) { + return String.fromCharCode((value >> 7) & 0xff) + + String.fromCharCode(value & 0xff); + } return String.fromCharCode((value >> 8) & 0xff) + String.fromCharCode(value & 0xff); }; @@ -732,10 +741,8 @@ var Font = (function () { */ hmtx = "\x01\xF4\x00\x00"; // Fake .notdef var width = 0, lsb = 0; - for (var i = 0; i < charstrings.length; i++) { - width = charstrings[i].charstring[0]; - hmtx += string16(width) + string16(lsb); - } + for (var i = 0; i < charstrings.length; i++) + hmtx += string16(charstrings[i].width) + string16(charstrings[i].lsb); hmtx = stringToArray(hmtx); createTableEntry(otf, offsets, "hmtx", hmtx); @@ -832,14 +839,14 @@ var Font = (function () { */ var FontsUtils = { _bytesArray: new Uint8Array(4), - integerToBytes: function fu_integerToBytes(value, bytesCount) { + integerToBytes: function fu_integerToBytes(value, bytesCount, signed) { var bytes = this._bytesArray; if (bytesCount == 1) { bytes.set([value]); return bytes[0]; } else if (bytesCount == 2) { - bytes.set([value >> 8, value]); + bytes.set([value >> 8, value & 0xff]); return [bytes[0], bytes[1]]; } else if (bytesCount == 4) { bytes.set([value >> 24, value >> 16, value >> 8, value]); @@ -1005,6 +1012,8 @@ var Type1Parser = function() { function decodeCharString(array) { var charstring = []; + var lsb = 0; + var width = 0; var z = 0; var value = ""; @@ -1043,14 +1052,30 @@ var Type1Parser = function() { } else { // TODO Clean this code + Gindex = Gindex || 1; if (value == 13) { - var charWidthVector = charstring[1]; - var leftSidebearing = charstring[0]; - - charstring.push(leftSidebearing, "hmoveto"); + width = charstring[1]; + lsb = charstring[0]; + //charstring.push(lsb, "hmoveto"); charstring.splice(0, 1); continue; + } else if (0 && lsb && value == 1) { // hstem + charstring[Gindex] += lsb; + lsb = 0; + } else if (0 && lsb && value == 22) { // hmoveto + error("hmoveto: " + charstring[Gindex]); + charstring[Gindex] += lsb; + lsb = 0; + } else if (0 && lsb && value == 14) { // enchar + var p = charstring[Gindex]; + if (IsNum(p)) { + charstring[Gindex] += lsb; + } else { + charstring.splice(Gindex + 1, 0, lsb); + } + lsb = 0; } + var Gindex = charstring.length; command = charStringDictionary[value]; } @@ -1080,7 +1105,7 @@ var Type1Parser = function() { charstring.push(value); } - return charstring; + return { charstring: charstring, width: width, lsb: lsb }; }; /** @@ -1107,19 +1132,21 @@ var Type1Parser = function() { length = parseInt(length); var data = eexecString.slice(i + 3, i + 3 + length); var encodedSubr = decrypt(data, kCharStringsEncryptionKey, 4); - var subr = decodeCharString(encodedSubr); + var str = decodeCharString(encodedSubr); - subrs.push(subr); + subrs.push(str.charstring); i += 3 + length; } else if (inGlyphs && c == 0x52) { length = parseInt(length); var data = eexecString.slice(i + 3, i + 3 + length); var encodedCharstring = decrypt(data, kCharStringsEncryptionKey, 4); - var subr = decodeCharString(encodedCharstring); + var str = decodeCharString(encodedCharstring); glyphs.push({ glyph: glyph, - data: subr + data: str.charstring, + lsb: str.lsb, + width: str.width }); i += 3 + length; } else if (inGlyphs && c == 0x2F) { @@ -1290,7 +1317,9 @@ CFF.prototype = { charstrings.push({ glyph: glyph, unicode: unicode, - charstring: glyphs[i].data + charstring: glyphs[i].data, + width: glyphs[i].width, + lsb: glyphs[i].lsb }); } }; From 0783f3a896e4662a01a4d2d6a66d9f8fa1dc5e56 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 28 Jun 2011 01:17:36 +0200 Subject: [PATCH 04/12] Next try for windows --- fonts.js | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/fonts.js b/fonts.js index fe42cbcc3..18869a556 100644 --- a/fonts.js +++ b/fonts.js @@ -189,7 +189,7 @@ var Font = (function () { return String.fromCharCode(byte ^ 0xff) + String.fromCharCode(value & 0xff); } else if (signed) { - return String.fromCharCode((value >> 7) & 0xff) + + return String.fromCharCode((value >> 8) & 0xff) + String.fromCharCode(value & 0xff); } return String.fromCharCode((value >> 8) & 0xff) + @@ -741,8 +741,13 @@ var Font = (function () { */ hmtx = "\x01\xF4\x00\x00"; // Fake .notdef var width = 0, lsb = 0; - for (var i = 0; i < charstrings.length; i++) - hmtx += string16(charstrings[i].width) + string16(charstrings[i].lsb); + for (var i = 0; i < charstrings.length; i++) { + var charstring = charstrings[i]; + if (fontCount == 1) { + log(charstring.width + "::" + charstring.lsb); + } + hmtx += string16(charstring.width) + string16(charstring.lsb, true); + } hmtx = stringToArray(hmtx); createTableEntry(otf, offsets, "hmtx", hmtx); @@ -1010,12 +1015,12 @@ var Type1Parser = function() { var kEscapeCommand = 12; - function decodeCharString(array) { + function decodeCharString(array, glyph) { var charstring = []; var lsb = 0; var width = 0; + var used = false; - var z = 0; var value = ""; var count = array.length; for (var i = 0; i < count; i++) { @@ -1056,24 +1061,26 @@ var Type1Parser = function() { if (value == 13) { width = charstring[1]; lsb = charstring[0]; - //charstring.push(lsb, "hmoveto"); + charstring.push(lsb, "hmoveto"); charstring.splice(0, 1); + used = true; continue; - } else if (0 && lsb && value == 1) { // hstem + } else if (!used && lsb && value == 1) { // hstem charstring[Gindex] += lsb; - lsb = 0; - } else if (0 && lsb && value == 22) { // hmoveto + used = true; + } else if (!used && lsb && value == 22) { // hmoveto error("hmoveto: " + charstring[Gindex]); charstring[Gindex] += lsb; - lsb = 0; - } else if (0 && lsb && value == 14) { // enchar + used = true; + } else if (!used && lsb && value == 14) { // enchar + log(glyph); var p = charstring[Gindex]; if (IsNum(p)) { charstring[Gindex] += lsb; } else { charstring.splice(Gindex + 1, 0, lsb); } - lsb = 0; + used = true; } var Gindex = charstring.length; @@ -1105,6 +1112,9 @@ var Type1Parser = function() { charstring.push(value); } + if (!used && lsb) + error("lsb has not been reported in " + fontName + " for charstring: " + charstring); + return { charstring: charstring, width: width, lsb: lsb }; }; @@ -1140,7 +1150,7 @@ var Type1Parser = function() { length = parseInt(length); var data = eexecString.slice(i + 3, i + 3 + length); var encodedCharstring = decrypt(data, kCharStringsEncryptionKey, 4); - var str = decodeCharString(encodedCharstring); + var str = decodeCharString(encodedCharstring, glyph); glyphs.push({ glyph: glyph, From a56e5ade22d177721edac881bc45db4aeb03a81f Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 28 Jun 2011 01:39:09 +0200 Subject: [PATCH 05/12] Next try for windows (2) --- fonts.js | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/fonts.js b/fonts.js index 18869a556..f52768e4c 100644 --- a/fonts.js +++ b/fonts.js @@ -183,14 +183,9 @@ var Font = (function () { }; function string16(value, signed) { - if (signed && value < 0) { - value = Math.abs(value); - var byte = (value >> 8) & 0xff; - return String.fromCharCode(byte ^ 0xff) + - String.fromCharCode(value & 0xff); - } else if (signed) { - return String.fromCharCode((value >> 8) & 0xff) + - String.fromCharCode(value & 0xff); + if (signed) { + value ^= 0xffff; + value += 1; } return String.fromCharCode((value >> 8) & 0xff) + String.fromCharCode(value & 0xff); @@ -743,8 +738,8 @@ var Font = (function () { var width = 0, lsb = 0; for (var i = 0; i < charstrings.length; i++) { var charstring = charstrings[i]; - if (fontCount == 1) { - log(charstring.width + "::" + charstring.lsb); + if (fontCount == 9) { + log(charstring.glyph + "::" + charstring.width + "::" + charstring.lsb); } hmtx += string16(charstring.width) + string16(charstring.lsb, true); } @@ -1061,7 +1056,7 @@ var Type1Parser = function() { if (value == 13) { width = charstring[1]; lsb = charstring[0]; - charstring.push(lsb, "hmoveto"); + //charstring.push(lsb, "hmoveto"); charstring.splice(0, 1); used = true; continue; From bfe035653302367cd75b157e0475f0b6a9cd3723 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 28 Jun 2011 13:06:31 +0200 Subject: [PATCH 06/12] Filled notdef in the cmap table --- fonts.js | 49 +++++++++++-------------------------------------- 1 file changed, 11 insertions(+), 38 deletions(-) diff --git a/fonts.js b/fonts.js index f52768e4c..847f5292e 100644 --- a/fonts.js +++ b/fonts.js @@ -182,11 +182,7 @@ var Font = (function () { return array; }; - function string16(value, signed) { - if (signed) { - value ^= 0xffff; - value += 1; - } + function string16(value) { return String.fromCharCode((value >> 8) & 0xff) + String.fromCharCode(value & 0xff); }; @@ -275,6 +271,7 @@ var Font = (function () { }; function createCMapTable(glyphs) { + glyphs.push({unicode: 0x000}); var ranges = getRanges(glyphs); var headerSize = (12 * 2 + (ranges.length * 4 * 2)); @@ -308,7 +305,7 @@ var Font = (function () { var range = ranges[i]; var start = range[0]; var end = range[1]; - var delta = (((start - 1) - bias) ^ 0xffff) + 1; + var delta = (((start - 1) - bias) ^ 0xffff); bias += (end - start + 1); startCount += string16(start); @@ -734,21 +731,18 @@ var Font = (function () { * while Windows use this data. So be careful if you hack on Linux and * have to touch the 'hmtx' table */ - hmtx = "\x01\xF4\x00\x00"; // Fake .notdef + hmtx = "\x00\x00\x00\x00"; // Fake .notdef var width = 0, lsb = 0; for (var i = 0; i < charstrings.length; i++) { var charstring = charstrings[i]; - if (fontCount == 9) { - log(charstring.glyph + "::" + charstring.width + "::" + charstring.lsb); - } - hmtx += string16(charstring.width) + string16(charstring.lsb, true); + hmtx += string16(charstring.width) + string16(0); } hmtx = stringToArray(hmtx); createTableEntry(otf, offsets, "hmtx", hmtx); /** MAXP */ maxp = "\x00\x00\x50\x00" + // Version number - string16(charstrings.length + 1); // Num of glyphs (+1 to pass the sanitizer...) + string16(charstrings.length + 1); // Num of glyphs maxp = stringToArray(maxp); createTableEntry(otf, offsets, "maxp", maxp); @@ -1050,35 +1044,14 @@ var Type1Parser = function() { command = charStringDictionary["12"][escape]; } else { - // TODO Clean this code - Gindex = Gindex || 1; if (value == 13) { width = charstring[1]; lsb = charstring[0]; - //charstring.push(lsb, "hmoveto"); + charstring.push(lsb, "hmoveto"); charstring.splice(0, 1); - used = true; continue; - } else if (!used && lsb && value == 1) { // hstem - charstring[Gindex] += lsb; - used = true; - } else if (!used && lsb && value == 22) { // hmoveto - error("hmoveto: " + charstring[Gindex]); - charstring[Gindex] += lsb; - used = true; - } else if (!used && lsb && value == 14) { // enchar - log(glyph); - var p = charstring[Gindex]; - if (IsNum(p)) { - charstring[Gindex] += lsb; - } else { - charstring.splice(Gindex + 1, 0, lsb); - } - used = true; } - var Gindex = charstring.length; - command = charStringDictionary[value]; } @@ -1107,9 +1080,6 @@ var Type1Parser = function() { charstring.push(value); } - if (!used && lsb) - error("lsb has not been reported in " + fontName + " for charstring: " + charstring); - return { charstring: charstring, width: width, lsb: lsb }; }; @@ -1366,6 +1336,9 @@ CFF.prototype = { var i = 0; while (true) { var obj = charstring[i]; + if (obj == undefined) { + error("unknow charstring command for " + i + " in " + charstring); + } if (obj.charAt) { switch (obj) { case "endchar": @@ -1379,7 +1352,7 @@ CFF.prototype = { } else if (command.charAt) { var cmd = this.commandsMap[command]; if (!cmd) - error(command); + error("Unknow command: " + command); if (IsArray(cmd)) { charstring.splice(j, 1, cmd[0], cmd[1]); From fe55204042b7225671e57cc78f06fdd7f58cacf5 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 28 Jun 2011 13:15:00 +0200 Subject: [PATCH 07/12] Add 1 to the number of metrics in the HHEA table and remove the mapping of .notdef --- fonts.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fonts.js b/fonts.js index 847f5292e..37b8dbcce 100644 --- a/fonts.js +++ b/fonts.js @@ -271,7 +271,6 @@ var Font = (function () { }; function createCMapTable(glyphs) { - glyphs.push({unicode: 0x000}); var ranges = getRanges(glyphs); var headerSize = (12 * 2 + (ranges.length * 4 * 2)); @@ -305,7 +304,7 @@ var Font = (function () { var range = ranges[i]; var start = range[0]; var end = range[1]; - var delta = (((start - 1) - bias) ^ 0xffff); + var delta = (((start - 1) - bias) ^ 0xffff) + 1; bias += (end - start + 1); startCount += string16(start); @@ -721,7 +720,7 @@ var Font = (function () { "\x00\x00" + // -reserved- "\x00\x00" + // -reserved- "\x00\x00" + // metricDataFormat - string16(charstrings.length) + string16(charstrings.length + 1) // Number of HMetrics ); createTableEntry(otf, offsets, "hhea", hhea); From 82928b14a170d24ae2e0f2a96150feabf3cbe042 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 28 Jun 2011 13:34:39 +0200 Subject: [PATCH 08/12] Handle division in hsbw to provide the correct information to the hmtx table --- fonts.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index 37b8dbcce..ecc21d9c0 100644 --- a/fonts.js +++ b/fonts.js @@ -1045,7 +1045,14 @@ var Type1Parser = function() { } else { // TODO Clean this code if (value == 13) { - width = charstring[1]; + if (charstring.length == 2) { + width = charstring[1]; + } else if (charstring.length == 4 && charstring[3] == "div") { + width = charstring[1] / charstring[2]; + } else { + error("Unsupported hsbw format: " + charstring); + } + lsb = charstring[0]; charstring.push(lsb, "hmoveto"); charstring.splice(0, 1); From e3dbb685f3f3931881eac02529b185db4ab39cfd Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 28 Jun 2011 17:26:52 +0200 Subject: [PATCH 09/12] Add more precision for positionning fonts by scaling the canvas --- pdf.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 48fc8f1ae..2d25cf707 100644 --- a/pdf.js +++ b/pdf.js @@ -2807,6 +2807,7 @@ var CanvasGraphics = (function() { return; } + this.current.fontName = fontName; this.current.fontSize = size; this.ctx.font = this.current.fontSize +'px "' + fontName + '", Symbol'; }, @@ -2850,7 +2851,11 @@ var CanvasGraphics = (function() { text = Fonts.charsToUnicode(text); this.ctx.translate(this.current.x, -1 * this.current.y); this.ctx.fillText(text, 0, 0); - this.current.x += this.ctx.measureText(text).width; + + this.ctx.scale(0.05, 1); + this.ctx.font = (this.current.fontSize * 20) + 'px "' + this.current.fontName + '", Symbol'; + this.current.x += this.ctx.measureText(text).width / 20; + this.ctx.scale(1, 1); } this.ctx.restore(); From 63e1601464a113f6927492d04332838be9e5f072 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 28 Jun 2011 17:35:15 +0200 Subject: [PATCH 10/12] Small cleanup --- fonts.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fonts.js b/fonts.js index ecc21d9c0..d69746993 100644 --- a/fonts.js +++ b/fonts.js @@ -832,7 +832,7 @@ var Font = (function () { */ var FontsUtils = { _bytesArray: new Uint8Array(4), - integerToBytes: function fu_integerToBytes(value, bytesCount, signed) { + integerToBytes: function fu_integerToBytes(value, bytesCount) { var bytes = this._bytesArray; if (bytesCount == 1) { @@ -1003,7 +1003,7 @@ var Type1Parser = function() { var kEscapeCommand = 12; - function decodeCharString(array, glyph) { + function decodeCharString(array) { var charstring = []; var lsb = 0; var width = 0; @@ -1121,7 +1121,7 @@ var Type1Parser = function() { length = parseInt(length); var data = eexecString.slice(i + 3, i + 3 + length); var encodedCharstring = decrypt(data, kCharStringsEncryptionKey, 4); - var str = decodeCharString(encodedCharstring, glyph); + var str = decodeCharString(encodedCharstring); glyphs.push({ glyph: glyph, @@ -1289,8 +1289,8 @@ CFF.prototype = { var charstrings = []; for (var i = 0; i < glyphs.length; i++) { - var glyph = glyphs[i].glyph; - var unicode = GlyphsUnicode[glyph]; + var glyph = glyphs[i]; + var unicode = GlyphsUnicode[glyph.glyph]; if (!unicode) { if (glyph != ".notdef") warn(glyph + " does not have an entry in the glyphs unicode dictionary"); @@ -1298,9 +1298,9 @@ CFF.prototype = { charstrings.push({ glyph: glyph, unicode: unicode, - charstring: glyphs[i].data, - width: glyphs[i].width, - lsb: glyphs[i].lsb + charstring: glyph.data, + width: glyph.width, + lsb: glyph.lsb }); } }; From 80f650b6bb95f3c2d10057b4d268f66af608eb97 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 28 Jun 2011 18:24:16 +0200 Subject: [PATCH 11/12] Add a fake canvas for scaling fonts to improve perfs --- fonts.js | 19 +++++++++++++++++-- pdf.js | 11 ++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/fonts.js b/fonts.js index d69746993..4ac5935b5 100644 --- a/fonts.js +++ b/fonts.js @@ -26,12 +26,15 @@ var fontName = ""; */ var kDisableFonts = false; + /** * Hold a map of decoded fonts and of the standard fourteen Type1 fonts and * their acronyms. * TODO Add the standard fourteen Type1 fonts list by default * http://cgit.freedesktop.org/poppler/poppler/tree/poppler/GfxFont.cc#n65 */ + +var kScalePrecision = 100; var Fonts = { _active: null, @@ -39,8 +42,9 @@ var Fonts = { return this._active; }, - set active(name) { + setActive: function fonts_setActive(name, size) { this._active = this[name]; + this.ctx.font = (size * kScalePrecision) + 'px "' + name + '"'; }, charsToUnicode: function fonts_chars2Unicode(chars) { @@ -77,6 +81,17 @@ var Fonts = { // Enter the translated string into the cache return active.cache[chars] = str; + }, + + get ctx() { + delete this.ctx; + var ctx = document.createElement("canvas").getContext("2d"); + ctx.scale(1 / kScalePrecision, 1); + return this.ctx = ctx; + }, + + measureText: function fonts_measureText(text) { + return this.ctx.measureText(text).width / kScalePrecision; } }; @@ -1292,7 +1307,7 @@ CFF.prototype = { var glyph = glyphs[i]; var unicode = GlyphsUnicode[glyph.glyph]; if (!unicode) { - if (glyph != ".notdef") + if (glyph.glyph != ".notdef") warn(glyph + " does not have an entry in the glyphs unicode dictionary"); } else { charstrings.push({ diff --git a/pdf.js b/pdf.js index 2d25cf707..f09ccd866 100644 --- a/pdf.js +++ b/pdf.js @@ -2797,19 +2797,20 @@ var CanvasGraphics = (function() { if (fontDescriptor && fontDescriptor.num) { var fontDescriptor = this.xref.fetchIfRef(fontDescriptor); fontName = fontDescriptor.get("FontName").name.replace("+", "_"); - Fonts.active = fontName; + Fonts.setActive(fontName, size); } if (!fontName) { // TODO: fontDescriptor is not available, fallback to default font this.current.fontSize = size; this.ctx.font = this.current.fontSize + 'px sans-serif'; + Fonts.setActive("sans-serif", this.current.fontSize); return; } this.current.fontName = fontName; this.current.fontSize = size; - this.ctx.font = this.current.fontSize +'px "' + fontName + '", Symbol'; + this.ctx.font = this.current.fontSize + 'px "' + this.current.fontName + '"'; }, setTextRenderingMode: function(mode) { TODO("text rendering mode"); @@ -2851,11 +2852,7 @@ var CanvasGraphics = (function() { text = Fonts.charsToUnicode(text); this.ctx.translate(this.current.x, -1 * this.current.y); this.ctx.fillText(text, 0, 0); - - this.ctx.scale(0.05, 1); - this.ctx.font = (this.current.fontSize * 20) + 'px "' + this.current.fontName + '", Symbol'; - this.current.x += this.ctx.measureText(text).width / 20; - this.ctx.scale(1, 1); + this.current.x += Fonts.measureText(text); } this.ctx.restore(); From 91399b50ef971cc4479866c4340017cca8e28ba7 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Wed, 29 Jun 2011 03:00:23 +0200 Subject: [PATCH 12/12] Use the shadow method in Fonts.ctx --- fonts.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fonts.js b/fonts.js index 19d16cbed..e25b2ae2d 100644 --- a/fonts.js +++ b/fonts.js @@ -84,10 +84,9 @@ var Fonts = { }, get ctx() { - delete this.ctx; var ctx = document.createElement("canvas").getContext("2d"); ctx.scale(1 / kScalePrecision, 1); - return this.ctx = ctx; + return shadow(this, "ctx", ctx); }, measureText: function fonts_measureText(text) {