From e13164eca6a37c71c01ffa5a3ea672a508de564b Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Fri, 1 Jul 2011 07:16:56 +0200 Subject: [PATCH] Read the text matrix from the Type1 font ascii header --- fonts.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- pdf.js | 6 ++++-- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/fonts.js b/fonts.js index bc20e22e1..1e32dfbc3 100644 --- a/fonts.js +++ b/fonts.js @@ -8,7 +8,7 @@ var isWorker = (typeof window == "undefined"); /** * Maximum file size of the font. */ -var kMaxFontFileSize = 200000; +var kMaxFontFileSize = 40000; /** * Maximum time to wait for a font to be loaded by @font-face @@ -77,6 +77,9 @@ var Fonts = (function Fonts() { measureCache = sizes[size] = Object.create(null); ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; }, + getActive: function fonts_getActive() { + return current; + }, charsToUnicode: function fonts_chars2Unicode(chars) { if (!charsCache) return chars; @@ -1386,7 +1389,57 @@ var Type1Parser = function() { } return extracted; - } + }, + + this.extractFontHeader = function t1_extractFontProgram(stream) { + var headerString = ""; + for (var i = 0; i < stream.length; i++) + headerString += String.fromCharCode(stream[i]); + + var info = { + textMatrix: null + }; + + function readNumberArray(str, index) { + var start = ++index; + var count = 0; + while ((c = str[index++]) != "]") + count++; + + var array = str.substr(start, count).split(" "); + for (var i = 0; i < array.length; i++) + array[i] = parseFloat(array[i]); + return array; + }; + + var token = ""; + var count = headerString.length; + for (var i = 0; i < count; i++) { + var c = headerString[i]; + if (c == " " || c == "\n") { + switch (token) { + case "/FontMatrix": + var matrix = readNumberArray(headerString, i + 1); + + // The FontMatrix is in unitPerEm, so make it pixels + for (var j = 0; j < matrix.length; j++) + matrix[j] *= 1000; + + // Make the angle into the right direction + matrix[2] *= -1; + + info.textMatrix = matrix; + break; + } + token = ""; + } else { + token += c; + } + } + + return info; + }; + }; /** @@ -1457,7 +1510,12 @@ var CFF = function(name, file, properties) { // Get the data block containing glyphs and subrs informations var length1 = file.dict.get("Length1"); var length2 = file.dict.get("Length2"); - file.skip(length1); + + var headerBlock = file.getBytes(length1); + var header = type1Parser.extractFontHeader(headerBlock); + for (var info in header) { + properties[info] = header[info]; + } // Decrypt the data blocks and retrieve it's content var eexecBlock = file.getBytes(length2); @@ -1700,6 +1758,7 @@ CFF.prototype = { "charstrings": this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs), true), "private": (function(self) { + log(properties.stemSnapH); var data = "\x8b\x14" + // defaultWidth "\x8b\x15" + // nominalWidth diff --git a/pdf.js b/pdf.js index 3e3654087..f0e58b1b7 100644 --- a/pdf.js +++ b/pdf.js @@ -3544,7 +3544,8 @@ var CanvasGraphics = (function() { capHeight: descriptor.get("CapHeight"), flags: descriptor.get("Flags"), italicAngle: descriptor.get("ItalicAngle"), - fixedPitch: false + fixedPitch: false, + textMatrix: IDENTITY_MATRIX.slice() }; return { @@ -3861,7 +3862,6 @@ var CanvasGraphics = (function() { // TODO: apply charSpacing, wordSpacing, textHScale this.ctx.save(); - this.ctx.transform.apply(this.ctx, this.current.textMatrix); this.ctx.scale(1, -1); if (this.ctx.$showText) { @@ -3869,6 +3869,8 @@ var CanvasGraphics = (function() { } else { text = Fonts.charsToUnicode(text); this.ctx.translate(this.current.x, -1 * this.current.y); + var matrix = Fonts.lookup(this.current.fontName).properties.textMatrix; + this.ctx.transform.apply(this.ctx, matrix); this.ctx.fillText(text, 0, 0); this.current.x += Fonts.measureText(text); }