From ff17a5db5aad39cdfde6b53e2a8267c5b0daf0fc Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Thu, 7 Jul 2011 01:02:42 +0200 Subject: [PATCH 01/36] Updated Dict object. Perf. Improv. --- pdf.js | 65 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/pdf.js b/pdf.js index 2151c0497..7dbc187fc 100644 --- a/pdf.js +++ b/pdf.js @@ -1917,32 +1917,37 @@ var Cmd = (function() { var Dict = (function() { function constructor() { - this.map = Object.create(null); + this.map = {}; } constructor.prototype = { - get: function(key) { - if (key in this.map) - return this.map[key]; - return null; - }, - get2: function(key1, key2) { - return this.get(key1) || this.get(key2); - }, - get3: function(key1, key2, key3) { - return this.get(key1) || this.get(key2) || this.get(key3); - }, - has: function(key) { - return key in this.map; + get: function(key1, key2, key3) { + var value; + if (typeof (value = this.map[key1]) != 'undefined' || key1 in map || typeof key2 == 'undefined') { + return value; + } + if (typeof (value = this.map[key2]) != 'undefined' || key2 in map || typeof key3 == 'undefined') { + return value; + } + + return this.map[key3] || null; }, + set: function(key, value) { this.map[key] = value; }, - forEach: function(aCallback) { - for (var key in this.map) - aCallback(key, this.map[key]); + + has: function(key) { + return key in this.map; + }, + + forEach: function(callback) { + for (var key in this.map) { + callback.call(null, key, this.map[key]); + } } }; + return constructor; })(); @@ -2459,8 +2464,8 @@ var Parser = (function() { return stream; }, filter: function(stream, dict, length) { - var filter = dict.get2('Filter', 'F'); - var params = dict.get2('DecodeParms', 'DP'); + var filter = dict.get('Filter', 'F'); + var params = dict.get('DecodeParms', 'DP'); if (IsName(filter)) return this.makeFilter(stream, filter.name, length, params); if (IsArray(filter)) { @@ -3472,7 +3477,7 @@ var CanvasGraphics = (function() { assertWellFormed(IsName(fontName), 'invalid font name'); fontName = fontName.name.replace('+', '_'); - var fontFile = descriptor.get3('FontFile', 'FontFile2', 'FontFile3'); + var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3'); if (!fontFile) error('FontFile not found for font: ' + fontName); fontFile = xref.fetchIfRef(fontFile); @@ -4204,7 +4209,7 @@ var CanvasGraphics = (function() { if (background) TODO('handle background colors'); - var cs = shading.get2('ColorSpace', 'CS'); + var cs = shading.get('ColorSpace', 'CS'); cs = ColorSpace.parse(cs, this.xref, this.res); var types = [null, @@ -4368,8 +4373,8 @@ var CanvasGraphics = (function() { var ctx = this.ctx; var dict = image.dict; - var w = dict.get2('Width', 'W'); - var h = dict.get2('Height', 'H'); + var w = dict.get('Width', 'W'); + var h = dict.get('Height', 'H'); // scale the image to the unit square ctx.scale(1 / w, -1 / h); @@ -4786,18 +4791,18 @@ var PDFImage = (function() { // TODO cache rendered images? var dict = image.dict; - this.width = dict.get2('Width', 'W'); - this.height = dict.get2('Height', 'H'); + this.width = dict.get('Width', 'W'); + this.height = dict.get('Height', 'H'); if (this.width < 1 || this.height < 1) error('Invalid image width or height'); - this.interpolate = dict.get2('Interpolate', 'I') || false; - this.imageMask = dict.get2('ImageMask', 'IM') || false; + this.interpolate = dict.get('Interpolate', 'I') || false; + this.imageMask = dict.get('ImageMask', 'IM') || false; var bitsPerComponent = image.bitsPerComponent; if (!bitsPerComponent) { - bitsPerComponent = dict.get2('BitsPerComponent', 'BPC'); + bitsPerComponent = dict.get('BitsPerComponent', 'BPC'); if (!bitsPerComponent) { if (this.imageMask) bitsPerComponent = 1; @@ -4807,11 +4812,11 @@ var PDFImage = (function() { } this.bpc = bitsPerComponent; - var colorSpace = dict.get2('ColorSpace', 'CS'); + var colorSpace = dict.get('ColorSpace', 'CS'); this.colorSpace = ColorSpace.parse(colorSpace, xref, res); this.numComps = this.colorSpace.numComps; - this.decode = dict.get2('Decode', 'D'); + this.decode = dict.get('Decode', 'D'); var mask = xref.fetchIfRef(image.dict.get('Mask')); var smask = xref.fetchIfRef(image.dict.get('SMask')); From 6eaad13132e6efda279ffc16cbddd0ce628b3f0c Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Wed, 6 Jul 2011 22:14:48 -0700 Subject: [PATCH 02/36] remove fontCount/fontName/kDisableFonts debug hacks and fix bug in font loading --- fonts.js | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/fonts.js b/fonts.js index f6620a0a0..2f6a550f8 100755 --- a/fonts.js +++ b/fonts.js @@ -15,20 +15,6 @@ var kMaxFontFileSize = 40000; */ var kMaxWaitForFontFace = 1000; -/** - * Useful for debugging when you want to certains operations depending on how - * many fonts are loaded. - */ -var fontCount = 0; -var fontName = ''; - -/** - * If for some reason one want to debug without fonts activated, it just need - * to turn this pref to true/false. - */ -var kDisableFonts = false; - - /** * Hold a map of decoded fonts and of the standard fourteen Type1 fonts and * their acronyms. @@ -253,7 +239,7 @@ var FontLoader = { src += ' }'; src += ''; for (var i = 0; i < names.length; ++i) { - src += '

Hi

'; + src += '

Hi

'; } src += ''; var frame = document.createElement('iframe'); @@ -420,12 +406,10 @@ var Font = (function() { this.font = Fonts.lookup(name).data; return; } - fontCount++; - fontName = name; // 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 (properties.ignore || kDisableFonts) { + if (properties.ignore) { Fonts.blacklistFont(name); return; } From 056a729115c2c2299fafc6d1c31efe135a9c78e4 Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Thu, 7 Jul 2011 16:06:45 +0200 Subject: [PATCH 03/36] Use .call instead of .apply. minor. --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 7dbc187fc..73fdeee2a 100644 --- a/pdf.js +++ b/pdf.js @@ -4989,7 +4989,7 @@ var PDFFunction = (function() { if (!typeFn) error('Unknown type of function'); - typeFn.apply(this, [fn, dict]); + typeFn.call(this, fn, dict); }; constructor.prototype = { From 42cdf6bf028afba0b7babded7c9855f6b6d150de Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Thu, 7 Jul 2011 16:51:44 +0200 Subject: [PATCH 04/36] Fixing typo in Dict --- pdf.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdf.js b/pdf.js index 73fdeee2a..72557ccd9 100644 --- a/pdf.js +++ b/pdf.js @@ -1923,10 +1923,10 @@ var Dict = (function() { constructor.prototype = { get: function(key1, key2, key3) { var value; - if (typeof (value = this.map[key1]) != 'undefined' || key1 in map || typeof key2 == 'undefined') { + if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map || typeof key2 == 'undefined') { return value; } - if (typeof (value = this.map[key2]) != 'undefined' || key2 in map || typeof key3 == 'undefined') { + if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map || typeof key3 == 'undefined') { return value; } From dc9316db2daa67e951a1055d2e0237b78798e4e6 Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Thu, 7 Jul 2011 17:03:24 +0200 Subject: [PATCH 05/36] Better debug at glyphs --- fonts.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fonts.js b/fonts.js index d85d40b2f..25fef9ac6 100755 --- a/fonts.js +++ b/fonts.js @@ -2,7 +2,7 @@ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ 'use strict'; - +var missingGlyphs = []; var isWorker = (typeof window == 'undefined'); /** @@ -1661,9 +1661,11 @@ CFF.prototype = { for (var i = 0; i < glyphs.length; i++) { var glyph = glyphs[i]; var unicode = GlyphsUnicode[glyph.glyph]; + if (!unicode) { if (glyph.glyph != '.notdef') { - warn(glyph + + missingGlyphs.push(glyph.glyph); + warn(glyph.glyph + ' does not have an entry in the glyphs unicode dictionary'); } } else { From da8f0120a5d4a2917acf860acc3453423ad27626 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 09:38:58 -0700 Subject: [PATCH 06/36] working separation cs --- pdf.js | 101 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 28 deletions(-) diff --git a/pdf.js b/pdf.js index 209027537..3829df975 100644 --- a/pdf.js +++ b/pdf.js @@ -1613,7 +1613,7 @@ var CCITTFaxStream = (function() { } if (this.byteAlign) - inputBits &= ~7; + this.inputBits &= ~7; var gotEOL = false; @@ -4601,8 +4601,14 @@ var ColorSpace = (function() { var hiVal = cs[2] + 1; var lookup = xref.fetchIfRef(cs[3]); return new IndexedCS(base, hiVal, lookup); + break; + case 'Separation': + var name = cs[1]; + var alt = ColorSpace.parse(cs[2], xref, res); + var tintFn = new PDFFunction(xref, xref.fetchIfRef(cs[3])); + return new TintCS("Separation", alt, tintFn); + break; case 'Lab': - case 'Seperation': case 'DeviceN': default: error("unrecognized color space object '" + mode + "'"); @@ -4615,6 +4621,44 @@ var ColorSpace = (function() { return constructor; })(); +var TintCS = (function() { + function constructor(name, base, tintFn) { + this.name = name; + this.numComps = 1; + this.defaultColor = [0]; + + this.base = base; + this.tintFn = tintFn; + } + + constructor.prototype = { + getRgb: function tintcs_getRgb(color) { + var tinted = this.tintFn.func(color); + return this.base.getRgb(tinted); + }, + getRgbBuffer: function tintcs_getRgbBuffer(input) { + var tintFn = this.tintFn; + var base = this.base; + + var length = 3 * input.length; + var rgbBuf = new Uint8Array(length); + var pos = 0; + + for (var i = 0, ii = input.length; i < ii; ++i) { + var scaled = input[i] / 255; + var tinted = tintFn.func([scaled]); + var rgb = base.getRgb(tinted); + for (var j = 0; j < 3; ++j) + rgbBuf[pos++] = Math.round(255 * rgb[j]); + } + + return rgbBuf; + } + }; + + return constructor; +})(); + var PatternCS = (function() { function constructor() { this.name = 'Pattern'; @@ -4655,7 +4699,9 @@ var IndexedCS = (function() { var numComps = base.numComps; var c = []; - for (var i = 0; i < numComps; ++i) + var start = color[0] * numComps; + + for (var i = start, ii = start + numComps; i < ii; ++i) c.push(lookup[i]); return this.base.getRgb(c); }, @@ -4693,7 +4739,7 @@ var DeviceGrayCS = (function() { return [c, c, c]; }, getRgbBuffer: function graycs_getRgbBuffer(input) { - var length = input.length; + var length = input.length * 3; var rgbBuf = new Uint8Array(length); for (var i = 0, j = 0; i < length; ++i) { var c = input[i]; @@ -4786,8 +4832,22 @@ var DeviceCmykCS = (function() { return [r, g, b]; }, getRgbBuffer: function cmykcs_getRgbBuffer(colorBuf) { - error('conversion from rgb to cmyk not implemented for images'); - return colorBuf; + var length = colorBuf.length / 4; + var rgbBuf = new Uint8Array(length * 3); + var rgbBufPos = 0; + var colorBufPos = 0; + + for (var i = 0; i < length; i++) { + var cmyk = []; + for (var j = 0; j < 4; ++j) + cmyk.push(colorBuf[colorBufPos++]/255); + + var rgb = this.getRgb(cmyk); + for (var j = 0; j < 3; ++j) + rgb[rgbBufPos++] = Math.round(rgb[j] * 255); + } + + return rgbBuf; } }; return constructor; @@ -4904,7 +4964,7 @@ var PDFImage = (function() { output[i] = Math.round(255 * ret / ((1 << bpc) - 1)); } } - return this.colorSpace.getRbaBuffer(output); + return output; }, getOpacity: function getOpacity() { var smask = this.smask; @@ -4936,32 +4996,17 @@ var PDFImage = (function() { var rowBytes = (width * numComps * bpc + 7) >> 3; var imgArray = this.image.getBytes(height * rowBytes); - var comps = this.getComponents(imgArray); + var comps = this.colorSpace.getRgbBuffer(this.getComponents(imgArray)); var compsPos = 0; var opacity = this.getOpacity(); var opacityPos = 0; var length = width * height * 4; - switch (numComps) { - case 1: - for (var i = 0; i < length; i += 4) { - var p = comps[compsPos++]; - buffer[i] = p; - buffer[i + 1] = p; - buffer[i + 2] = p; - buffer[i + 3] = opacity[opacityPos++]; - } - break; - case 3: - for (var i = 0; i < length; i += 4) { - buffer[i] = comps[compsPos++]; - buffer[i + 1] = comps[compsPos++]; - buffer[i + 2] = comps[compsPos++]; - buffer[i + 3] = opacity[opacityPos++]; - } - break; - default: - TODO('Images with ' + numComps + ' components per pixel'); + for (var i = 0; i < length; i += 4) { + buffer[i] = comps[compsPos++]; + buffer[i + 1] = comps[compsPos++]; + buffer[i + 2] = comps[compsPos++]; + buffer[i + 3] = opacity[opacityPos++]; } }, fillGrayBuffer: function fillGrayBuffer(buffer) { From eba0b18b19bb9951eb8fc4267a5670e616d1aed7 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Thu, 7 Jul 2011 12:51:48 -0400 Subject: [PATCH 07/36] allow custom rules to be defined in local.mk --- .gitignore | 2 ++ Makefile | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 95de9fb8e..9e2d0f211 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*~ pdf.pdf intelisa.pdf openweb_tm-PRINT.pdf +local.mk diff --git a/Makefile b/Makefile index c6971d025..9b2817fc4 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,9 @@ BUILD_DIR := build DEFAULT_BROWSERS := test/resources/browser_manifests/browser_manifest.json DEFAULT_TESTS := test/test_manifest.json +# Let folks define custom rules for their clones. +-include local.mk + # JS files needed for pdf.js. # This list doesn't account for the 'worker' directory. PDF_JS_FILES = \ @@ -156,5 +159,5 @@ clean: help: @echo "Read the comments in the Makefile for guidance."; -.PHONY: all test browser-test font-test shell-test \ +.PHONY:: all test browser-test font-test shell-test \ shell-msg lint clean web compiler help server From 1007e279c6b86b85803304f41b506434ce588988 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 11:01:14 -0700 Subject: [PATCH 08/36] added comments --- pdf.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pdf.js b/pdf.js index 3829df975..c2760b546 100644 --- a/pdf.js +++ b/pdf.js @@ -4520,10 +4520,24 @@ var CanvasGraphics = (function() { })(); var ColorSpace = (function() { + // Constructor should define this.numComps, this.defaultColor, this.name function constructor() { error('should not call ColorSpace constructor'); }; + constructor.prototype = { + // Input: array of size numComps representing color component values + // Output: array of rgb values, each value ranging from [0.1] + getRgb: function cs_getRgb(color) { + error('Should not call ColorSpace.getRgb'); + }, + // Input: Uint8Array of component values, each value scaled to [0,255] + // Output: Uint8Array of rgb values, each value scaled to [0,255] + getRgbBuffer: function cs_getRgbBuffer(input) { + error('Should not call ColorSpace.getRgbBuffer'); + } + }; + constructor.parse = function colorspace_parse(cs, xref, res) { if (IsName(cs)) { var colorSpaces = res.get('ColorSpace'); From 54ae4fc6cba5a346a204c2720d09ac93ab2ea746 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 11:13:39 -0700 Subject: [PATCH 09/36] changed name from TintCS to SeparationCS --- pdf.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pdf.js b/pdf.js index c2760b546..02efa39be 100644 --- a/pdf.js +++ b/pdf.js @@ -4620,7 +4620,7 @@ var ColorSpace = (function() { var name = cs[1]; var alt = ColorSpace.parse(cs[2], xref, res); var tintFn = new PDFFunction(xref, xref.fetchIfRef(cs[3])); - return new TintCS("Separation", alt, tintFn); + return new SeparationCS(alt, tintFn); break; case 'Lab': case 'DeviceN': @@ -4635,11 +4635,11 @@ var ColorSpace = (function() { return constructor; })(); -var TintCS = (function() { - function constructor(name, base, tintFn) { - this.name = name; +var SeparationCS = (function() { + function constructor(base, tintFn) { + this.name = "Separation"; this.numComps = 1; - this.defaultColor = [0]; + this.defaultColor = [1]; this.base = base; this.tintFn = tintFn; From 6ae81e1f8c55b3cca7defd3c7e201e3d063a493c Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 11:21:41 -0700 Subject: [PATCH 10/36] cleanup --- pdf.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pdf.js b/pdf.js index 02efa39be..e9830f872 100644 --- a/pdf.js +++ b/pdf.js @@ -4708,15 +4708,14 @@ var IndexedCS = (function() { constructor.prototype = { getRgb: function graycs_getRgb(color) { - var lookup = this.lookup; - var base = this.base; var numComps = base.numComps; - var c = []; var start = color[0] * numComps; + var c = []; for (var i = start, ii = start + numComps; i < ii; ++i) - c.push(lookup[i]); + c.push(this.lookup[i]); + return this.base.getRgb(c); }, getRgbBuffer: function graycs_getRgbBuffer(input) { From b62eddd93712e3dd83ea0a6d8f258edbbb2711c6 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 11:26:29 -0700 Subject: [PATCH 11/36] fixed to index cs --- pdf.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pdf.js b/pdf.js index e9830f872..d28a74945 100644 --- a/pdf.js +++ b/pdf.js @@ -4707,7 +4707,7 @@ var IndexedCS = (function() { } constructor.prototype = { - getRgb: function graycs_getRgb(color) { + getRgb: function indexcs_getRgb(color) { var numComps = base.numComps; var start = color[0] * numComps; @@ -4718,8 +4718,7 @@ var IndexedCS = (function() { return this.base.getRgb(c); }, - getRgbBuffer: function graycs_getRgbBuffer(input) { - var base = this.base; + getRgbBuffer: function indexcs_getRgbBuffer(input) { var numComps = base.numComps; var lookup = this.lookup; var length = input.length; @@ -4727,13 +4726,13 @@ var IndexedCS = (function() { var baseBuf = new Uint8Array(length * numComps); var baseBufPos = 0; for (var i = 0; i < length; ++i) { - var lookupPos = input[i]; + var lookupPos = input[i] * numComps; for (var j = 0; j < numComps; ++j) { baseBuf[baseBufPos++] = lookup[lookupPos + j]; } } - return base.getRgbBuffer(baseBuf); + return this.base.getRgbBuffer(baseBuf); } }; return constructor; From 39624e91739e24ebf52c83df19863c96b26cb922 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 11:46:52 -0700 Subject: [PATCH 12/36] fix performance issue with SeparationCS --- pdf.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pdf.js b/pdf.js index d28a74945..78ac9eb3b 100644 --- a/pdf.js +++ b/pdf.js @@ -4658,15 +4658,16 @@ var SeparationCS = (function() { var rgbBuf = new Uint8Array(length); var pos = 0; + var numComps = base.numComps; + var baseBuf = new Uint8Array(numComps * input.length); for (var i = 0, ii = input.length; i < ii; ++i) { var scaled = input[i] / 255; var tinted = tintFn.func([scaled]); - var rgb = base.getRgb(tinted); - for (var j = 0; j < 3; ++j) - rgbBuf[pos++] = Math.round(255 * rgb[j]); + for (var j = 0; j < numComps; ++j) + baseBuf[pos++] = 255 * tinted[j]; } + return base.getRgbBuffer(baseBuf); - return rgbBuf; } }; @@ -4856,7 +4857,7 @@ var DeviceCmykCS = (function() { var rgb = this.getRgb(cmyk); for (var j = 0; j < 3; ++j) - rgb[rgbBufPos++] = Math.round(rgb[j] * 255); + rgbBuf[rgbBufPos++] = Math.round(rgb[j] * 255); } return rgbBuf; From f34308efd3304707357988374f277e43cd634448 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 11:47:49 -0700 Subject: [PATCH 13/36] cleanup --- pdf.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdf.js b/pdf.js index 78ac9eb3b..ecd5f48a3 100644 --- a/pdf.js +++ b/pdf.js @@ -4646,11 +4646,11 @@ var SeparationCS = (function() { } constructor.prototype = { - getRgb: function tintcs_getRgb(color) { + getRgb: function sepcs_getRgb(color) { var tinted = this.tintFn.func(color); return this.base.getRgb(tinted); }, - getRgbBuffer: function tintcs_getRgbBuffer(input) { + getRgbBuffer: function sepcs_getRgbBuffer(input) { var tintFn = this.tintFn; var base = this.base; From 15a50e423786b828252c4b679e8434c41287e08c Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 11:48:34 -0700 Subject: [PATCH 14/36] cleanup --- pdf.js | 1 - 1 file changed, 1 deletion(-) diff --git a/pdf.js b/pdf.js index ecd5f48a3..c41031ecc 100644 --- a/pdf.js +++ b/pdf.js @@ -4655,7 +4655,6 @@ var SeparationCS = (function() { var base = this.base; var length = 3 * input.length; - var rgbBuf = new Uint8Array(length); var pos = 0; var numComps = base.numComps; From 8db37875445e3fc664b79261f14c222a152709d1 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 11:56:10 -0700 Subject: [PATCH 15/36] fix bug with unref var --- pdf.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index c41031ecc..d41a98c27 100644 --- a/pdf.js +++ b/pdf.js @@ -4719,6 +4719,7 @@ var IndexedCS = (function() { return this.base.getRgb(c); }, getRgbBuffer: function indexcs_getRgbBuffer(input) { + var base = this.base; var numComps = base.numComps; var lookup = this.lookup; var length = input.length; @@ -4732,7 +4733,7 @@ var IndexedCS = (function() { } } - return this.base.getRgbBuffer(baseBuf); + return base.getRgbBuffer(baseBuf); } }; return constructor; From 8ac2367fa0f2434bbc51995b6430cb8bf2cda7d3 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 16:48:04 -0700 Subject: [PATCH 16/36] not refer fonts by name, instead use id --- fonts.js | 77 +++++++++++++++++++++++++++++++------------------------- pdf.js | 22 ++++++++-------- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/fonts.js b/fonts.js index 2f6a550f8..d068e6714 100755 --- a/fonts.js +++ b/fonts.js @@ -24,17 +24,18 @@ var kMaxWaitForFontFace = 1000; var Fonts = (function Fonts() { var kScalePrecision = 40; - var fonts = Object.create(null); + var fonts = []; if (!isWorker) { var ctx = document.createElement('canvas').getContext('2d'); ctx.scale(1 / kScalePrecision, 1); } - function Font(name, data, properties) { + function FontInfo(name, data, properties, id) { this.name = name; this.data = data; this.properties = properties; + this.id = id; this.loading = true; this.charsCache = Object.create(null); this.sizes = []; @@ -44,27 +45,31 @@ var Fonts = (function Fonts() { var charsCache; var measureCache; + var fontCount = 0; + return { registerFont: function fonts_registerFont(fontName, data, properties) { - fonts[fontName] = new Font(fontName, data, properties); + fonts.push(new FontInfo(fontName, data, properties, fontCount)); + return fontCount++; }, blacklistFont: function fonts_blacklistFont(fontName) { - registerFont(fontName, null, {}); + var id = registerFont(fontName, null, {}); markLoaded(fontName); + return id; }, - lookup: function fonts_lookup(fontName) { - return fonts[fontName]; + lookupById: function fonts_lookupById(id) { + return fonts[id]; }, - setActive: function fonts_setActive(fontName, size) { + setActive: function fonts_setActive(font, size) { // |current| can be null is fontName is a built-in font // (e.g. "sans-serif") - if ((current = fonts[fontName])) { + if ((current = fonts[font.id])) { charsCache = current.charsCache; var sizes = current.sizes; if (!(measureCache = sizes[size])) measureCache = sizes[size] = Object.create(null); } - ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; + ctx.font = (size * kScalePrecision) + 'px "' + font.loadedName + '"'; }, charsToUnicode: function fonts_chars2Unicode(chars) { if (!charsCache) @@ -118,8 +123,8 @@ var FontLoader = { bind: function(fonts, callback) { function checkFontsLoaded() { for (var i = 0; i < fonts.length; i++) { - var font = fonts[i]; - if (Fonts.lookup(font.name).loading) { + var id = fonts[i].fontDict.fontObj.id; + if (Fonts.lookupById(id).loading) { return false; } } @@ -131,28 +136,29 @@ var FontLoader = { return true; } - var rules = [], names = []; + var rules = [], names = [], ids = []; for (var i = 0; i < fonts.length; i++) { var font = fonts[i]; - if (!Fonts.lookup(font.name)) { - var obj = new Font(font.name, font.file, font.properties); - var str = ''; - var data = Fonts.lookup(font.name).data; - var length = data.length; - for (var j = 0; j < length; j++) - str += String.fromCharCode(data[j]); + var obj = new Font(font.name, font.file, font.properties); + font.fontDict.fontObj = obj; - var rule = isWorker ? obj.bindWorker(str) : obj.bindDOM(str); - if (rule) { - rules.push(rule); - names.push(font.name); - } + var str = ''; + var data = Fonts.lookupById(obj.id).data; + var length = data.length; + for (var j = 0; j < length; j++) + str += String.fromCharCode(data[j]); + + var rule = isWorker ? obj.bindWorker(str) : obj.bindDOM(str); + if (rule) { + rules.push(rule); + names.push(obj.loadedName); + ids.push(obj.id); } } if (!isWorker && rules.length) { - FontLoader.prepareFontLoadEvent(rules, names); + FontLoader.prepareFontLoadEvent(rules, names, ids); } if (!checkFontsLoaded()) { @@ -167,7 +173,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(rules, names, ids) { /** 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 @@ -209,7 +215,7 @@ var FontLoader = { function(e) { var fontNames = JSON.parse(e.data); for (var i = 0; i < fontNames.length; ++i) { - var font = Fonts.lookup(fontNames[i]); + var font = Fonts.lookupById(ids[i]); font.loading = false; } var evt = document.createEvent('Events'); @@ -402,15 +408,16 @@ var Font = (function() { this.encoding = properties.encoding; // If the font has already been decoded simply return it - if (Fonts.lookup(name)) { - this.font = Fonts.lookup(name).data; - return; - } + //if (Fonts.lookup(name)) { + // this.font = Fonts.lookup(name).data; + // return; + //} // 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 (properties.ignore) { - Fonts.blacklistFont(name); + this.id = Fonts.blacklistFont(name); + this.loadedName = 'pdfFont' + this.id; return; } @@ -437,7 +444,9 @@ var Font = (function() { break; } this.data = data; - Fonts.registerFont(name, data, properties); + + this.id = Fonts.registerFont(name, data, properties); + this.loadedName = 'pdfFont' + this.id; }; function stringToArray(str) { @@ -1124,7 +1133,7 @@ var Font = (function() { }, bindDOM: function font_bindDom(data) { - var fontName = this.name; + var fontName = this.loadedName; // Add the font-face rule to the document var url = ('url(data:' + this.mimetype + ';base64,' + diff --git a/pdf.js b/pdf.js index d41a98c27..64a25210f 100644 --- a/pdf.js +++ b/pdf.js @@ -3605,9 +3605,10 @@ var CanvasGraphics = (function() { return { name: fontName, - file: fontFile, - properties: properties - }; + fontDict: fontDict, + file: fontFile, + properties: properties + }; }, beginDrawing: function(mediaBox) { @@ -3686,6 +3687,7 @@ var CanvasGraphics = (function() { var font = xref.fetchIfRef(fontRes.get(args[0].name)); assertWellFormed(IsDict(font)); if (!font.translated) { + // sbarman marker font.translated = this.translateFont(font, xref, resources); if (fonts && font.translated) { // keep track of each font we translated so the caller can @@ -3868,25 +3870,23 @@ var CanvasGraphics = (function() { return; var fontName = ''; - var fontDescriptor = font.get('FontDescriptor'); - if (fontDescriptor && fontDescriptor.num) { - var fontDescriptor = this.xref.fetchIfRef(fontDescriptor); - fontName = fontDescriptor.get('FontName').name.replace('+', '_'); - } + var fontObj = font.fontObj; + if (fontObj) + fontName = fontObj.loadedName; if (!fontName) { // TODO: fontDescriptor is not available, fallback to default font fontName = 'sans-serif'; } - this.current.fontName = fontName; + this.current.font = fontObj; this.current.fontSize = size; if (this.ctx.$setFont) { this.ctx.$setFont(fontName, size); } else { this.ctx.font = size + 'px "' + fontName + '"'; - Fonts.setActive(fontName, size); + Fonts.setActive(font, size); } }, setTextRenderingMode: function(mode) { @@ -3931,7 +3931,7 @@ var CanvasGraphics = (function() { text = Fonts.charsToUnicode(text); this.ctx.translate(this.current.x, -1 * this.current.y); - var font = Fonts.lookup(this.current.fontName); + var font = Fonts.lookupById(this.current.font.id); if (font && font.properties.textMatrix) this.ctx.transform.apply(this.ctx, font.properties.textMatrix); From c39eae3ce932832e1275ec0b1f3fec5226390cc6 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 17:15:53 -0700 Subject: [PATCH 17/36] fixed up minor bugs --- fonts.js | 28 +++++++++++++--------------- pdf.js | 3 +-- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/fonts.js b/fonts.js index d068e6714..48c99d8a7 100755 --- a/fonts.js +++ b/fonts.js @@ -31,11 +31,13 @@ var Fonts = (function Fonts() { ctx.scale(1 / kScalePrecision, 1); } - function FontInfo(name, data, properties, id) { + var fontCount = 0; + + function FontInfo(name, data, properties) { this.name = name; this.data = data; this.properties = properties; - this.id = id; + this.id = fontCount++; this.loading = true; this.charsCache = Object.create(null); this.sizes = []; @@ -45,12 +47,11 @@ var Fonts = (function Fonts() { var charsCache; var measureCache; - var fontCount = 0; - return { registerFont: function fonts_registerFont(fontName, data, properties) { - fonts.push(new FontInfo(fontName, data, properties, fontCount)); - return fontCount++; + var font = new FontInfo(fontName, data, properties); + fonts.push(font); + return font.id; }, blacklistFont: function fonts_blacklistFont(fontName) { var id = registerFont(fontName, null, {}); @@ -122,8 +123,8 @@ var FontLoader = { bind: function(fonts, callback) { function checkFontsLoaded() { - for (var i = 0; i < fonts.length; i++) { - var id = fonts[i].fontDict.fontObj.id; + for (var i = 0; i < allIds.length; i++) { + var id = allIds[i]; if (Fonts.lookupById(id).loading) { return false; } @@ -136,12 +137,15 @@ var FontLoader = { return true; } + var allIds = []; var rules = [], names = [], ids = []; + for (var i = 0; i < fonts.length; i++) { var font = fonts[i]; var obj = new Font(font.name, font.file, font.properties); font.fontDict.fontObj = obj; + allIds.push(obj.id); var str = ''; var data = Fonts.lookupById(obj.id).data; @@ -160,7 +164,7 @@ var FontLoader = { if (!isWorker && rules.length) { FontLoader.prepareFontLoadEvent(rules, names, ids); } - + if (!checkFontsLoaded()) { document.documentElement.addEventListener( 'pdfjsFontLoad', checkFontsLoaded, false); @@ -407,12 +411,6 @@ var Font = (function() { this.name = name; this.encoding = properties.encoding; - // If the font has already been decoded simply return it - //if (Fonts.lookup(name)) { - // this.font = Fonts.lookup(name).data; - // return; - //} - // 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 (properties.ignore) { diff --git a/pdf.js b/pdf.js index 64a25210f..a2526f362 100644 --- a/pdf.js +++ b/pdf.js @@ -3687,7 +3687,6 @@ var CanvasGraphics = (function() { var font = xref.fetchIfRef(fontRes.get(args[0].name)); assertWellFormed(IsDict(font)); if (!font.translated) { - // sbarman marker font.translated = this.translateFont(font, xref, resources); if (fonts && font.translated) { // keep track of each font we translated so the caller can @@ -3886,7 +3885,7 @@ var CanvasGraphics = (function() { this.ctx.$setFont(fontName, size); } else { this.ctx.font = size + 'px "' + fontName + '"'; - Fonts.setActive(font, size); + Fonts.setActive(fontObj, size); } }, setTextRenderingMode: function(mode) { From 619a5216787f47e79fdf3647b9c37007b10324c7 Mon Sep 17 00:00:00 2001 From: sbarman Date: Thu, 7 Jul 2011 17:37:27 -0700 Subject: [PATCH 18/36] minor fix --- fonts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index 48c99d8a7..262746ac6 100755 --- a/fonts.js +++ b/fonts.js @@ -1124,7 +1124,7 @@ var Font = (function() { action: 'font', data: { raw: data, - fontName: this.name, + fontName: this.loadedName, mimetype: this.mimetype } }); From 7fb940c4ba5f7fb909bc453920f22314776b2456 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 8 Jul 2011 01:02:14 -0700 Subject: [PATCH 19/36] revert a couple changes from the last merge --- fonts.js | 3 --- pdf.js | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/fonts.js b/fonts.js index 40259a36e..57e2e73c8 100755 --- a/fonts.js +++ b/fonts.js @@ -2,7 +2,6 @@ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ 'use strict'; -var missingGlyphs = []; var isWorker = (typeof window == 'undefined'); /** @@ -1645,10 +1644,8 @@ CFF.prototype = { for (var i = 0; i < glyphs.length; i++) { var glyph = glyphs[i]; var unicode = GlyphsUnicode[glyph.glyph]; - if (!unicode) { if (glyph.glyph != '.notdef') { - missingGlyphs.push(glyph.glyph); warn(glyph.glyph + ' does not have an entry in the glyphs unicode dictionary'); } diff --git a/pdf.js b/pdf.js index 64eb2d452..e332e12e5 100644 --- a/pdf.js +++ b/pdf.js @@ -1917,7 +1917,7 @@ var Cmd = (function() { var Dict = (function() { function constructor() { - this.map = {}; + this.map = Object.create(null); } constructor.prototype = { From 82b6b4ead85de32a3d57f1b0a6473985181f6785 Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Fri, 8 Jul 2011 14:57:40 +0200 Subject: [PATCH 20/36] min. perf. Dict --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index e332e12e5..f2ea1fd05 100644 --- a/pdf.js +++ b/pdf.js @@ -1943,7 +1943,7 @@ var Dict = (function() { forEach: function(callback) { for (var key in this.map) { - callback.call(null, key, this.map[key]); + callback(key, this.map[key]); } } }; From 44048712126d57b9cb652e229406867ae5e5105f Mon Sep 17 00:00:00 2001 From: sbarman Date: Fri, 8 Jul 2011 08:14:34 -0700 Subject: [PATCH 21/36] fixed font loading bug --- fonts.js | 11 ++++++----- pdf.js | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/fonts.js b/fonts.js index 262746ac6..c275227a9 100755 --- a/fonts.js +++ b/fonts.js @@ -61,16 +61,16 @@ var Fonts = (function Fonts() { lookupById: function fonts_lookupById(id) { return fonts[id]; }, - setActive: function fonts_setActive(font, size) { + setActive: function fonts_setActive(fontName, fontObj, size) { // |current| can be null is fontName is a built-in font // (e.g. "sans-serif") - if ((current = fonts[font.id])) { + if (fontObj && (current = fonts[fontObj.id])) { charsCache = current.charsCache; var sizes = current.sizes; if (!(measureCache = sizes[size])) measureCache = sizes[size] = Object.create(null); } - ctx.font = (size * kScalePrecision) + 'px "' + font.loadedName + '"'; + ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; }, charsToUnicode: function fonts_chars2Unicode(chars) { if (!charsCache) @@ -161,6 +161,7 @@ var FontLoader = { } } + this.listeningForFontLoad = false; if (!isWorker && rules.length) { FontLoader.prepareFontLoadEvent(rules, names, ids); } @@ -213,7 +214,7 @@ var FontLoader = { div.innerHTML = html; document.body.appendChild(div); - if (!this.listeneningForFontLoad) { + if (!this.listeningForFontLoad) { window.addEventListener( 'message', function(e) { @@ -227,7 +228,7 @@ var FontLoader = { document.documentElement.dispatchEvent(evt); }, false); - this.listeneningForFontLoad = true; + this.listeningForFontLoad = true; } // XXX we should have a time-out here too, and maybe fire diff --git a/pdf.js b/pdf.js index a2526f362..c30c89614 100644 --- a/pdf.js +++ b/pdf.js @@ -3885,7 +3885,7 @@ var CanvasGraphics = (function() { this.ctx.$setFont(fontName, size); } else { this.ctx.font = size + 'px "' + fontName + '"'; - Fonts.setActive(fontObj, size); + Fonts.setActive(fontName, fontObj, size); } }, setTextRenderingMode: function(mode) { From 7b659fd605cc76dc7c86d3ae95076434630c8961 Mon Sep 17 00:00:00 2001 From: sbarman Date: Fri, 8 Jul 2011 10:04:52 -0700 Subject: [PATCH 22/36] fixed case when font cannot be found --- fonts.js | 4 ++++ pdf.js | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/fonts.js b/fonts.js index c275227a9..093b9ec31 100755 --- a/fonts.js +++ b/fonts.js @@ -69,7 +69,11 @@ var Fonts = (function Fonts() { var sizes = current.sizes; if (!(measureCache = sizes[size])) measureCache = sizes[size] = Object.create(null); + } else { + charsCache = null; + measureCache = null } + ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; }, charsToUnicode: function fonts_chars2Unicode(chars) { diff --git a/pdf.js b/pdf.js index c30c89614..85490baee 100644 --- a/pdf.js +++ b/pdf.js @@ -3930,10 +3930,12 @@ var CanvasGraphics = (function() { text = Fonts.charsToUnicode(text); this.ctx.translate(this.current.x, -1 * this.current.y); - var font = Fonts.lookupById(this.current.font.id); - if (font && font.properties.textMatrix) - this.ctx.transform.apply(this.ctx, font.properties.textMatrix); - + var font = this.current.font; + if (font) { + var fontInfo = Fonts.lookupById(font.id); + if (fontInfo && fontInfo.properties.textMatrix) + this.ctx.transform.apply(this.ctx, fontInfo.properties.textMatrix); + } this.ctx.fillText(text, 0, 0); this.current.x += Fonts.measureText(text); } From 4391e2985ae3af82b611ebed76ddf28b6b7435c3 Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Fri, 8 Jul 2011 23:19:03 +0200 Subject: [PATCH 23/36] Adding AsciiHexDecode Filter --- pdf.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/pdf.js b/pdf.js index f2ea1fd05..563b9ca3f 100644 --- a/pdf.js +++ b/pdf.js @@ -904,6 +904,47 @@ var Ascii85Stream = (function() { return constructor; })(); +var AsciiHexStream = (function() { + function constructor(str) { + this.str = str; + this.dict = str.dict; + + DecodeStream.call(this); + } + + constructor.prototype = Object.create(DecodeStream.prototype); + + constructor.prototype.readBlock = function() { + var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n, + decodeLength, buffer, bufferLength, i, length; + + decodeLength = (bytes.length + 1) / 2; + buffer = this.ensureBuffer(this.bufferLength + decodeLength); + bufferLength = this.bufferLength; + + for(i = 0, length = bytes.length; i < length; i++) { + c = String.fromCharCode(bytes[i]); + while (Lexer.isSpace(c) && (i+1) < length) { + c = String.fromCharCode(bytes[++i]); + } + + if((i+1) < length && (bytes[i+1] !== gtCode)) { + n = String.fromCharCode(bytes[++i]); + buffer[bufferLength++] = Number('0x'+c+n); + } else { + if(bytes[i] !== gtCode) { // EOD marker at an odd number, behave as if a 0 followed the last digit. + buffer[bufferLength++] = Number('0x'+c+'0'); + } + } + } + + this.bufferLength = bufferLength; + this.eof = true; + }; + + return constructor; +})(); + var CCITTFaxStream = (function() { var ccittEOL = -2; @@ -2496,6 +2537,8 @@ var Parser = (function() { return new JpegStream(bytes, stream.dict); } else if (name == 'ASCII85Decode') { return new Ascii85Stream(stream); + } else if (name == 'ASCIIHexDecode') { + return new AsciiHexStream(stream); } else if (name == 'CCITTFaxDecode') { TODO('implement fax stream'); return new CCITTFaxStream(stream, params); From f88d05e3b543ee7637f313912cead9b313b2f7e3 Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Fri, 8 Jul 2011 23:21:14 +0200 Subject: [PATCH 24/36] Adding ASCIIHexDecode pdf to test/pdfs --- test/pdfs/asciihexdecode.pdf | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 test/pdfs/asciihexdecode.pdf diff --git a/test/pdfs/asciihexdecode.pdf b/test/pdfs/asciihexdecode.pdf new file mode 100644 index 000000000..f3bd457ec --- /dev/null +++ b/test/pdfs/asciihexdecode.pdf @@ -0,0 +1,55 @@ +%PDF-1.0 +1 0 obj +<< + /Pages 2 0 R + /Type /Catalog +>> +endobj +2 0 obj +<< + /Count 1 + /Kids [ 3 0 R ] + /Type /Pages +>> +endobj +3 0 obj +<< + /MediaBox [ 0 0 795 842 ] + /Parent 2 0 R + /Contents 4 0 R + /Resources << + /Font << + /F1 << + /Name /F1 + /BaseFont /Helvetica + /Subtype /Type1 + /Type /Font + >> + >> + >> + /Type /Page +>> +endobj +4 0 obj +<< + /Filter /ASCIIHexDecode + /Length 111 +>>stream +42540A2F46312033302054660A333530203735302054640A323020544C0A312054720A2848656C6C6F20776F726C642920546A0A45540A> +endstream +endobj +xref +0 5 +0000000000 65535 f +0000000010 00000 n +0000000067 00000 n +0000000136 00000 n +0000000373 00000 n +trailer +<< + /Root 1 0 R + /Size 5 +>> +startxref +568 +%%EOF From f6eb9cecd39a85db6a3da574a13bef512e97767b Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 8 Jul 2011 14:58:19 -0700 Subject: [PATCH 25/36] avoid font lookup by id in showText --- fonts.js | 1 + pdf.js | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/fonts.js b/fonts.js index 380a0ea30..1f1db3652 100755 --- a/fonts.js +++ b/fonts.js @@ -413,6 +413,7 @@ function getUnicodeRangeFor(value) { var Font = (function() { 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 diff --git a/pdf.js b/pdf.js index eef6deed5..1666ce658 100644 --- a/pdf.js +++ b/pdf.js @@ -3925,24 +3925,24 @@ var CanvasGraphics = (function() { showText: function(text) { // TODO: apply charSpacing, wordSpacing, textHScale - this.ctx.save(); - this.ctx.transform.apply(this.ctx, this.current.textMatrix); - this.ctx.scale(1, -1); + var ctx = this.ctx; + var current = this.current; + + ctx.save(); + ctx.transform.apply(ctx, current.textMatrix); + ctx.scale(1, -1); if (this.ctx.$showText) { - this.ctx.$showText(this.current.y, Fonts.charsToUnicode(text)); + ctx.$showText(current.y, Fonts.charsToUnicode(text)); } else { text = Fonts.charsToUnicode(text); - this.ctx.translate(this.current.x, -1 * this.current.y); + ctx.translate(this.current.x, -1 * this.current.y); var font = this.current.font; - if (font) { - var fontInfo = Fonts.lookupById(font.id); - if (fontInfo && fontInfo.properties.textMatrix) - this.ctx.transform.apply(this.ctx, fontInfo.properties.textMatrix); - } - this.ctx.fillText(text, 0, 0); - this.current.x += Fonts.measureText(text); + if (font) + ctx.transform.apply(ctx, font.textMatrix); + ctx.fillText(text, 0, 0); + current.x += Fonts.measureText(text); } this.ctx.restore(); From 6fecf59ca7b68605639730232b078eac7339a91e Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 8 Jul 2011 15:13:33 -0700 Subject: [PATCH 26/36] address review comments --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 1666ce658..e357732f2 100644 --- a/pdf.js +++ b/pdf.js @@ -3936,7 +3936,7 @@ var CanvasGraphics = (function() { ctx.$showText(current.y, Fonts.charsToUnicode(text)); } else { text = Fonts.charsToUnicode(text); - ctx.translate(this.current.x, -1 * this.current.y); + ctx.translate(current.x, -1 * current.y); var font = this.current.font; if (font) From 396dbe51351c481c7176fe94195eb49ab5caf79d Mon Sep 17 00:00:00 2001 From: sbarman Date: Fri, 8 Jul 2011 15:28:04 -0700 Subject: [PATCH 27/36] fix encoding table --- pdf.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index eef6deed5..c14213eb1 100644 --- a/pdf.js +++ b/pdf.js @@ -3487,7 +3487,19 @@ var CanvasGraphics = (function() { if (fontDict.has('Encoding')) { var encoding = xref.fetchIfRef(fontDict.get('Encoding')); if (IsDict(encoding)) { - // Build a map between codes and glyphs + // Build a map of between codes and glyphs + // Load the base encoding + 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]]; + } else { + TODO('need to load default encoding'); + } + + // Load the differences between the base and original var differences = encoding.get('Differences'); var index = 0; for (var j = 0; j < differences.length; j++) { From ae867e3a9c98dd55d8dbb250771b8ef891b88dcb Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Sat, 9 Jul 2011 00:30:46 +0200 Subject: [PATCH 28/36] Using map for hex conversion and left-shift for secure division --- pdf.js | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/pdf.js b/pdf.js index 563b9ca3f..69a25f051 100644 --- a/pdf.js +++ b/pdf.js @@ -912,28 +912,55 @@ var AsciiHexStream = (function() { DecodeStream.call(this); } + var hexvalueMap = { + 9: -1, // \t + 32: -1, // space + 48: 0, + 49: 1, + 50: 2, + 51: 3, + 52: 4, + 53: 5, + 54: 6, + 55: 7, + 56: 8, + 57: 9, + 65: 10, + 66: 11, + 67: 12, + 68: 13, + 69: 14, + 70: 15, + 97: 10, + 98: 11, + 99: 12, + 100: 13, + 101: 14, + 102: 15 + }; + constructor.prototype = Object.create(DecodeStream.prototype); constructor.prototype.readBlock = function() { var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n, decodeLength, buffer, bufferLength, i, length; - decodeLength = (bytes.length + 1) / 2; + decodeLength = (bytes.length + 1) >> 1; buffer = this.ensureBuffer(this.bufferLength + decodeLength); bufferLength = this.bufferLength; for(i = 0, length = bytes.length; i < length; i++) { - c = String.fromCharCode(bytes[i]); - while (Lexer.isSpace(c) && (i+1) < length) { - c = String.fromCharCode(bytes[++i]); + c = hexvalueMap[bytes[i]]; + while (c == -1 && (i+1) < length) { + c = hexvalueMap[bytes[++i]]; } if((i+1) < length && (bytes[i+1] !== gtCode)) { - n = String.fromCharCode(bytes[++i]); - buffer[bufferLength++] = Number('0x'+c+n); + n = hexvalueMap[bytes[++i]]; + buffer[bufferLength++] = c*16+n; } else { if(bytes[i] !== gtCode) { // EOD marker at an odd number, behave as if a 0 followed the last digit. - buffer[bufferLength++] = Number('0x'+c+'0'); + buffer[bufferLength++] = c*16; } } } From 0b6c0db9310376f04658a45bb19b2c2791064082 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 8 Jul 2011 16:36:50 -0700 Subject: [PATCH 29/36] move unicode translation cache into Font --- fonts.js | 78 +++++++++++++++++++++++++++++--------------------------- pdf.js | 8 +++--- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/fonts.js b/fonts.js index 1f1db3652..7bdf7cefc 100755 --- a/fonts.js +++ b/fonts.js @@ -38,12 +38,10 @@ var Fonts = (function Fonts() { this.properties = properties; this.id = fontCount++; this.loading = true; - this.charsCache = Object.create(null); this.sizes = []; } var current; - var charsCache; var measureCache; return { @@ -64,51 +62,15 @@ var Fonts = (function Fonts() { // |current| can be null is fontName is a built-in font // (e.g. "sans-serif") if (fontObj && (current = fonts[fontObj.id])) { - charsCache = current.charsCache; var sizes = current.sizes; if (!(measureCache = sizes[size])) measureCache = sizes[size] = Object.create(null); } else { - charsCache = null; measureCache = null } ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; }, - charsToUnicode: function fonts_chars2Unicode(chars) { - if (!charsCache) - return chars; - - // if we translated this string before, just grab it from the cache - var str = charsCache[chars]; - if (str) - return str; - - // translate the string using the font's encoding - var encoding = current ? current.properties.encoding : null; - if (!encoding) - return chars; - - str = ''; - for (var i = 0; i < chars.length; ++i) { - var charcode = chars.charCodeAt(i); - var unicode = encoding[charcode]; - - // Check if the glyph has already been converted - if (!IsNum(unicode)) - unicode = encoding[unicode] = GlyphsUnicode[unicode.name]; - - // Handle surrogate pairs - if (unicode > 0xFFFF) { - str += String.fromCharCode(unicode & 0xFFFF); - unicode >>= 16; - } - str += String.fromCharCode(unicode); - } - - // Enter the translated string into the cache - return charsCache[chars] = str; - }, measureText: function fonts_measureText(text) { var width; if (measureCache && (width = measureCache[text])) @@ -1146,6 +1108,46 @@ var Font = (function() { styleSheet.insertRule(rule, styleSheet.cssRules.length); return rule; + }, + + charsToUnicode: function fonts_chars2Unicode(chars) { + var charsCache = this.charsCache; + + // if we translated this string before, just grab it from the cache + if (charsCache) { + var str = charsCache[chars]; + if (str) + return str; + } + + // translate the string using the font's encoding + var encoding = this.encoding; + if (!encoding) + return chars; + + // lazily create the translation cache + if (!charsCache) + charsCache = this.charsCache = Object.create(null); + + str = ''; + for (var i = 0; i < chars.length; ++i) { + var charcode = chars.charCodeAt(i); + var unicode = encoding[charcode]; + + // Check if the glyph has already been converted + if (!IsNum(unicode)) + unicode = encoding[unicode] = GlyphsUnicode[unicode.name]; + + // Handle surrogate pairs + if (unicode > 0xFFFF) { + str += String.fromCharCode(unicode & 0xFFFF); + unicode >>= 16; + } + str += String.fromCharCode(unicode); + } + + // Enter the translated string into the cache + return charsCache[chars] = str; } }; diff --git a/pdf.js b/pdf.js index e357732f2..8fb56bccf 100644 --- a/pdf.js +++ b/pdf.js @@ -3933,14 +3933,14 @@ var CanvasGraphics = (function() { ctx.scale(1, -1); if (this.ctx.$showText) { - ctx.$showText(current.y, Fonts.charsToUnicode(text)); + ctx.$showText(current.y, text); } else { - text = Fonts.charsToUnicode(text); ctx.translate(current.x, -1 * current.y); - var font = this.current.font; - if (font) + if (font) { ctx.transform.apply(ctx, font.textMatrix); + text = font.charsToUnicode(text); + } ctx.fillText(text, 0, 0); current.x += Fonts.measureText(text); } From 5820f4b1513d7637a7fbe1e262af963036db630a Mon Sep 17 00:00:00 2001 From: sbarman Date: Fri, 8 Jul 2011 17:35:25 -0700 Subject: [PATCH 30/36] fix tiling colorspace --- pdf.js | 64 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/pdf.js b/pdf.js index bf757c0b4..1f03c3020 100644 --- a/pdf.js +++ b/pdf.js @@ -4021,14 +4021,28 @@ var CanvasGraphics = (function() { var cs = this.getFillColorSpace(); if (cs.name == 'Pattern') { - var patternName = arguments[0]; - this.setFillPattern(patternName); + var length = arguments.length; + var base = cs.base; + if (base) { + var baseComps = base.numComps; + + if (baseComps != length - 1) + error("invalid base color for pattern colorspace"); + + var color = []; + for (var i = 0; i < baseComps; ++i) + color.push(arguments[i]); + + color = base.getRgb(color); + } + var patternName = arguments[length - 1]; + this.setFillPattern(patternName, base, color); } else { // TODO real impl this.setFillColor.apply(this, arguments); } }, - setFillPattern: function(patternName) { + setFillPattern: function(patternName, baseCS, color) { if (!IsName(patternName)) error("Bad args to getPattern"); @@ -4046,7 +4060,7 @@ var CanvasGraphics = (function() { var patternFn = types[typeNum]; if (!patternFn) error("Unhandled pattern type"); - patternFn.call(this, pattern, dict); + patternFn.call(this, pattern, dict, baseCS, color); }, setShadingPattern: function(pattern, dict) { var matrix = dict.get("Matrix"); @@ -4069,7 +4083,7 @@ var CanvasGraphics = (function() { this.ctx.fillRect(0,0,0,0); this.transform.apply(this, inv); }, - setTilingPattern: function(pattern, dict) { + setTilingPattern: function(pattern, dict, baseCS, color) { function multiply(m, tm) { var a = m[0] * tm[0] + m[1] * tm[2]; var b = m[0] * tm[1] + m[1] * tm[3]; @@ -4083,17 +4097,6 @@ var CanvasGraphics = (function() { this.save(); var ctx = this.ctx; - var paintType = dict.get('PaintType'); - switch (paintType) { - case PAINT_TYPE_COLORED: - // should go to default for color space - ctx.fillStyle = this.makeCssRgb(1, 1, 1); - ctx.strokeStyle = this.makeCssRgb(0, 0, 0); - break; - case PAINT_TYPE_UNCOLORED: - default: - error('Unsupported paint type'); - } TODO('TilingType'); @@ -4124,6 +4127,21 @@ var CanvasGraphics = (function() { var savedCtx = ctx; this.ctx = tmpCtx; + var paintType = dict.get('PaintType'); + switch (paintType) { + case PAINT_TYPE_COLORED: + // should go to default for color space + tmpCtx.fillStyle = this.makeCssRgb(1, 1, 1); + tmpCtx.strokeStyle = this.makeCssRgb(0, 0, 0); + break; + case PAINT_TYPE_UNCOLORED: + tmpCtx.fillStyle = this.makeCssRgb.apply(this, baseCS.getRgb(color)); + tmpCtx.strokeStyle = this.makeCssRgb.apply(this, baseCS.getRgb(color)); + break; + default: + error('Unsupported paint type'); + } + // normalize transform matrix so each step // takes up the entire tmpCanvas (need to remove white borders) if (matrix[1] === 0 && matrix[2] === 0) { @@ -4247,8 +4265,12 @@ var CanvasGraphics = (function() { var typeNum = shading.get('ShadingType'); var shadingFn = types[typeNum]; + + // Most likely we will not implement other types of shading + // unless the browser supports them if (!shadingFn) - error("Unknown or NYI type of shading '"+ typeNum +"'"); + TODO("Unknown or NYI type of shading '"+ typeNum +"'"); + return shadingFn.call(this, shading, cs); }, getAxialShading: function(sh, cs) { @@ -4626,7 +4648,10 @@ var ColorSpace = (function() { return new DeviceCmykCS(); break; case 'Pattern': - return new PatternCS(); + var baseCS = cs[1]; + if (baseCS) + baseCS = ColorSpace.parse(baseCS, xref, res); + return new PatternCS(baseCS); break; case 'Indexed': var base = ColorSpace.parse(cs[1], xref, res); @@ -4692,8 +4717,9 @@ var SeparationCS = (function() { })(); var PatternCS = (function() { - function constructor() { + function constructor(baseCS) { this.name = 'Pattern'; + this.base = baseCS; } constructor.prototype = {}; From 4a7fe7cb5d9a35b0bc67aaade6dfa476890b9caa Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 8 Jul 2011 17:57:03 -0700 Subject: [PATCH 31/36] move text measurement into Font --- fonts.js | 68 ++++++++++++++++++++++++++++++-------------------------- pdf.js | 13 +++++------ 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/fonts.js b/fonts.js index 7bdf7cefc..2591d2c2c 100755 --- a/fonts.js +++ b/fonts.js @@ -22,14 +22,7 @@ var kMaxWaitForFontFace = 1000; */ var Fonts = (function Fonts() { - var kScalePrecision = 40; var fonts = []; - - if (!isWorker) { - var ctx = document.createElement('canvas').getContext('2d'); - ctx.scale(1 / kScalePrecision, 1); - } - var fontCount = 0; function FontInfo(name, data, properties) { @@ -42,7 +35,6 @@ var Fonts = (function Fonts() { } var current; - var measureCache; return { registerFont: function fonts_registerFont(fontName, data, properties) { @@ -57,28 +49,6 @@ var Fonts = (function Fonts() { }, lookupById: function fonts_lookupById(id) { return fonts[id]; - }, - setActive: function fonts_setActive(fontName, fontObj, size) { - // |current| can be null is fontName is a built-in font - // (e.g. "sans-serif") - if (fontObj && (current = fonts[fontObj.id])) { - var sizes = current.sizes; - if (!(measureCache = sizes[size])) - measureCache = sizes[size] = Object.create(null); - } else { - measureCache = null - } - - ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; - }, - measureText: function fonts_measureText(text) { - var width; - if (measureCache && (width = measureCache[text])) - return width; - width = ctx.measureText(text).width / kScalePrecision; - if (measureCache) - measureCache[text] = width; - return width; } }; })(); @@ -364,6 +334,14 @@ function getUnicodeRangeFor(value) { return -1; } +var MeasureText = { + currentCache: null, + currentFont: null, + currentSize: 0, + ctx: null, + sizes: Object.create(null) +}; + /** * 'Font' is the class the outside world should use, it encapsulate all the font * decoding logics whatever type it is (assuming the font type is supported). @@ -373,6 +351,8 @@ function getUnicodeRangeFor(value) { * type1Font.bind(); */ var Font = (function() { + var kScalePrecision = 40; + var constructor = function font_constructor(name, file, properties) { this.name = name; this.textMatrix = properties.textMatrix || IDENTITY_MATRIX; @@ -1110,7 +1090,7 @@ var Font = (function() { return rule; }, - charsToUnicode: function fonts_chars2Unicode(chars) { + charsToUnicode: function fonts_charsToUnicode(chars) { var charsCache = this.charsCache; // if we translated this string before, just grab it from the cache @@ -1148,6 +1128,32 @@ var Font = (function() { // Enter the translated string into the cache return charsCache[chars] = str; + }, + + measureText: function fonts_measureText(text, size) { + if (MeasureText.currentFont != this || + MeasureText.currentSize != size) { + var ctx = MeasureText.ctx; + if (!ctx) { + ctx = MeasureText.ctx = document.createElement('canvas').getContext('2d'); + ctx.scale(1 / kScalePrecision, 1); + } + ctx.font = (size * kScalePrecision) + 'px "' + this.loadedName + '"'; + MeasureText.currentFont = this; + MeasureText.currentSize = size; + var cache = MeasureText.sizes[size]; + if (!cache) + cache = MeasureText.sizes[size] = Object.create(null); + MeasureText.currentCache = cache; + } + + var key = size + "$" + text; + var width = MeasureText.currentCache[key]; + if (width) + return width; + var ctx = MeasureText.ctx; + width = ctx.measureText(text).width / kScalePrecision; + return MeasureText.currentCache[key] = width; } }; diff --git a/pdf.js b/pdf.js index c85e6f26b..b412f72a2 100644 --- a/pdf.js +++ b/pdf.js @@ -3972,7 +3972,6 @@ var CanvasGraphics = (function() { this.ctx.$setFont(fontName, size); } else { this.ctx.font = size + 'px "' + fontName + '"'; - Fonts.setActive(fontName, fontObj, size); } }, setTextRenderingMode: function(mode) { @@ -4018,16 +4017,14 @@ var CanvasGraphics = (function() { ctx.$showText(current.y, text); } else { ctx.translate(current.x, -1 * current.y); - var font = this.current.font; - if (font) { - ctx.transform.apply(ctx, font.textMatrix); - text = font.charsToUnicode(text); - } + var font = current.font; + ctx.transform.apply(ctx, font.textMatrix); + text = font.charsToUnicode(text); ctx.fillText(text, 0, 0); - current.x += Fonts.measureText(text); + current.x += font.measureText(text, current.fontSize); } - this.ctx.restore(); + ctx.restore(); }, showSpacedText: function(arr) { for (var i = 0; i < arr.length; ++i) { From c06c14a72a370b12cd8b97c421b6751ade3bf99b Mon Sep 17 00:00:00 2001 From: sbarman Date: Fri, 8 Jul 2011 18:24:22 -0700 Subject: [PATCH 32/36] fix to font loading code --- fonts.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fonts.js b/fonts.js index 7bdf7cefc..289f13672 100755 --- a/fonts.js +++ b/fonts.js @@ -184,7 +184,8 @@ var FontLoader = { 'message', function(e) { var fontNames = JSON.parse(e.data); - for (var i = 0; i < fontNames.length; ++i) { + // set all the fonts to loaded (not sure if this is correct) + for (var i = 0; i < ids.length; ++i) { var font = Fonts.lookupById(ids[i]); font.loading = false; } From 5bf4fcba9bae5b3f905af98b0e85a59ec23e724e Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 8 Jul 2011 18:45:38 -0700 Subject: [PATCH 33/36] properly fix font loading, shaon's code didn't work after all --- fonts.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fonts.js b/fonts.js index 072d75623..ec89b3a58 100755 --- a/fonts.js +++ b/fonts.js @@ -154,9 +154,8 @@ var FontLoader = { 'message', function(e) { var fontNames = JSON.parse(e.data); - // set all the fonts to loaded (not sure if this is correct) - for (var i = 0; i < ids.length; ++i) { - var font = Fonts.lookupById(ids[i]); + for (var i = 0; i < fontNames.length; ++i) { + var font = Fonts.lookupById(fontNames[i].substring(7) | 0); font.loading = false; } var evt = document.createEvent('Events'); From f2a4756c77147b04e83e048fb2be0892ab88c654 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 8 Jul 2011 18:51:20 -0700 Subject: [PATCH 34/36] backout font measurement change, it is breaking tests --- fonts.js | 68 ++++++++++++++++++++++++++------------------------------ pdf.js | 13 ++++++----- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/fonts.js b/fonts.js index ec89b3a58..5b020e899 100755 --- a/fonts.js +++ b/fonts.js @@ -22,7 +22,14 @@ var kMaxWaitForFontFace = 1000; */ var Fonts = (function Fonts() { + var kScalePrecision = 40; var fonts = []; + + if (!isWorker) { + var ctx = document.createElement('canvas').getContext('2d'); + ctx.scale(1 / kScalePrecision, 1); + } + var fontCount = 0; function FontInfo(name, data, properties) { @@ -35,6 +42,7 @@ var Fonts = (function Fonts() { } var current; + var measureCache; return { registerFont: function fonts_registerFont(fontName, data, properties) { @@ -49,6 +57,28 @@ var Fonts = (function Fonts() { }, lookupById: function fonts_lookupById(id) { return fonts[id]; + }, + setActive: function fonts_setActive(fontName, fontObj, size) { + // |current| can be null is fontName is a built-in font + // (e.g. "sans-serif") + if (fontObj && (current = fonts[fontObj.id])) { + var sizes = current.sizes; + if (!(measureCache = sizes[size])) + measureCache = sizes[size] = Object.create(null); + } else { + measureCache = null + } + + ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; + }, + measureText: function fonts_measureText(text) { + var width; + if (measureCache && (width = measureCache[text])) + return width; + width = ctx.measureText(text).width / kScalePrecision; + if (measureCache) + measureCache[text] = width; + return width; } }; })(); @@ -334,14 +364,6 @@ function getUnicodeRangeFor(value) { return -1; } -var MeasureText = { - currentCache: null, - currentFont: null, - currentSize: 0, - ctx: null, - sizes: Object.create(null) -}; - /** * 'Font' is the class the outside world should use, it encapsulate all the font * decoding logics whatever type it is (assuming the font type is supported). @@ -351,8 +373,6 @@ var MeasureText = { * type1Font.bind(); */ var Font = (function() { - var kScalePrecision = 40; - var constructor = function font_constructor(name, file, properties) { this.name = name; this.textMatrix = properties.textMatrix || IDENTITY_MATRIX; @@ -1090,7 +1110,7 @@ var Font = (function() { return rule; }, - charsToUnicode: function fonts_charsToUnicode(chars) { + charsToUnicode: function fonts_chars2Unicode(chars) { var charsCache = this.charsCache; // if we translated this string before, just grab it from the cache @@ -1128,32 +1148,6 @@ var Font = (function() { // Enter the translated string into the cache return charsCache[chars] = str; - }, - - measureText: function fonts_measureText(text, size) { - if (MeasureText.currentFont != this || - MeasureText.currentSize != size) { - var ctx = MeasureText.ctx; - if (!ctx) { - ctx = MeasureText.ctx = document.createElement('canvas').getContext('2d'); - ctx.scale(1 / kScalePrecision, 1); - } - ctx.font = (size * kScalePrecision) + 'px "' + this.loadedName + '"'; - MeasureText.currentFont = this; - MeasureText.currentSize = size; - var cache = MeasureText.sizes[size]; - if (!cache) - cache = MeasureText.sizes[size] = Object.create(null); - MeasureText.currentCache = cache; - } - - var key = size + "$" + text; - var width = MeasureText.currentCache[key]; - if (width) - return width; - var ctx = MeasureText.ctx; - width = ctx.measureText(text).width / kScalePrecision; - return MeasureText.currentCache[key] = width; } }; diff --git a/pdf.js b/pdf.js index b38bc4eec..a40adbec7 100644 --- a/pdf.js +++ b/pdf.js @@ -3972,6 +3972,7 @@ var CanvasGraphics = (function() { this.ctx.$setFont(fontName, size); } else { this.ctx.font = size + 'px "' + fontName + '"'; + Fonts.setActive(fontName, fontObj, size); } }, setTextRenderingMode: function(mode) { @@ -4017,14 +4018,16 @@ var CanvasGraphics = (function() { ctx.$showText(current.y, text); } else { ctx.translate(current.x, -1 * current.y); - var font = current.font; - ctx.transform.apply(ctx, font.textMatrix); - text = font.charsToUnicode(text); + var font = this.current.font; + if (font) { + ctx.transform.apply(ctx, font.textMatrix); + text = font.charsToUnicode(text); + } ctx.fillText(text, 0, 0); - current.x += font.measureText(text, current.fontSize); + current.x += Fonts.measureText(text); } - ctx.restore(); + this.ctx.restore(); }, showSpacedText: function(arr) { for (var i = 0; i < arr.length; ++i) { From adb619941cc5d8b59bf6109926985d4de8243fd0 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Fri, 8 Jul 2011 19:28:24 -0700 Subject: [PATCH 35/36] simplify font measurement code, bug is now fixed in nightlies, no need to hack around it --- fonts.js | 32 +------------------------------- pdf.js | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 46 deletions(-) diff --git a/fonts.js b/fonts.js index 7bdf7cefc..27d003197 100755 --- a/fonts.js +++ b/fonts.js @@ -22,14 +22,7 @@ var kMaxWaitForFontFace = 1000; */ var Fonts = (function Fonts() { - var kScalePrecision = 40; var fonts = []; - - if (!isWorker) { - var ctx = document.createElement('canvas').getContext('2d'); - ctx.scale(1 / kScalePrecision, 1); - } - var fontCount = 0; function FontInfo(name, data, properties) { @@ -42,7 +35,6 @@ var Fonts = (function Fonts() { } var current; - var measureCache; return { registerFont: function fonts_registerFont(fontName, data, properties) { @@ -57,28 +49,6 @@ var Fonts = (function Fonts() { }, lookupById: function fonts_lookupById(id) { return fonts[id]; - }, - setActive: function fonts_setActive(fontName, fontObj, size) { - // |current| can be null is fontName is a built-in font - // (e.g. "sans-serif") - if (fontObj && (current = fonts[fontObj.id])) { - var sizes = current.sizes; - if (!(measureCache = sizes[size])) - measureCache = sizes[size] = Object.create(null); - } else { - measureCache = null - } - - ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; - }, - measureText: function fonts_measureText(text) { - var width; - if (measureCache && (width = measureCache[text])) - return width; - width = ctx.measureText(text).width / kScalePrecision; - if (measureCache) - measureCache[text] = width; - return width; } }; })(); @@ -1110,7 +1080,7 @@ var Font = (function() { return rule; }, - charsToUnicode: function fonts_chars2Unicode(chars) { + charsToUnicode: function fonts_charsToUnicode(chars) { var charsCache = this.charsCache; // if we translated this string before, just grab it from the cache diff --git a/pdf.js b/pdf.js index c85e6f26b..912963157 100644 --- a/pdf.js +++ b/pdf.js @@ -3972,7 +3972,6 @@ var CanvasGraphics = (function() { this.ctx.$setFont(fontName, size); } else { this.ctx.font = size + 'px "' + fontName + '"'; - Fonts.setActive(fontName, fontObj, size); } }, setTextRenderingMode: function(mode) { @@ -4010,24 +4009,25 @@ var CanvasGraphics = (function() { var ctx = this.ctx; var current = this.current; - ctx.save(); - ctx.transform.apply(ctx, current.textMatrix); - ctx.scale(1, -1); - if (this.ctx.$showText) { ctx.$showText(current.y, text); } else { - ctx.translate(current.x, -1 * current.y); - var font = this.current.font; - if (font) { - ctx.transform.apply(ctx, font.textMatrix); - text = font.charsToUnicode(text); - } - ctx.fillText(text, 0, 0); - current.x += Fonts.measureText(text); - } + ctx.save(); - this.ctx.restore(); + ctx.transform.apply(ctx, current.textMatrix); + ctx.scale(1, -1); + ctx.translate(current.x, -1 * current.y); + + var font = current.font; + ctx.transform.apply(ctx, font.textMatrix); + + text = font.charsToUnicode(text); + + ctx.fillText(text, 0, 0); + current.x += ctx.measureText(text).width; + + ctx.restore(); + } }, showSpacedText: function(arr) { for (var i = 0; i < arr.length; ++i) { From a5237dd60e0bce310255ef831cd922a8490192a7 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Sat, 9 Jul 2011 16:45:23 -0700 Subject: [PATCH 36/36] address review comment --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 912963157..bb4f75030 100644 --- a/pdf.js +++ b/pdf.js @@ -4016,7 +4016,7 @@ var CanvasGraphics = (function() { ctx.transform.apply(ctx, current.textMatrix); ctx.scale(1, -1); - ctx.translate(current.x, -1 * current.y); + ctx.translate(current.x, -current.y); var font = current.font; ctx.transform.apply(ctx, font.textMatrix);