From 855d2ccde538f58fa8d42a11337f0a4282ebbc28 Mon Sep 17 00:00:00 2001 From: Haebaru Date: Sun, 9 Sep 2012 17:12:02 +0900 Subject: [PATCH 01/17] Update l10n/ja/viewer.properties --- l10n/ja/viewer.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/l10n/ja/viewer.properties b/l10n/ja/viewer.properties index c8bfde461..eb584d5e7 100644 --- a/l10n/ja/viewer.properties +++ b/l10n/ja/viewer.properties @@ -50,6 +50,10 @@ thumb_page_title={{page}} ページ # number. thumb_page_canvas=ページの縮小版 {{page}} +# Context menu +page_rotate_cw=Rotate Clockwise +page_rotate_ccw=Rotate Counter-Clockwise + # Search panel button title and messages search=検索 search_terms_not_found=(見つかりませんでした) From f825e58658c609aa70a3618c119135bdfc5348d4 Mon Sep 17 00:00:00 2001 From: Haebaru Date: Sun, 9 Sep 2012 17:38:39 +0900 Subject: [PATCH 02/17] Update l10n/ja/viewer.properties --- l10n/ja/viewer.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/l10n/ja/viewer.properties b/l10n/ja/viewer.properties index eb584d5e7..b868dbfd2 100644 --- a/l10n/ja/viewer.properties +++ b/l10n/ja/viewer.properties @@ -51,8 +51,8 @@ thumb_page_title={{page}} ページ thumb_page_canvas=ページの縮小版 {{page}} # Context menu -page_rotate_cw=Rotate Clockwise -page_rotate_ccw=Rotate Counter-Clockwise +page_rotate_cw=右回転 +page_rotate_ccw=左回転 # Search panel button title and messages search=検索 From 62734a2d971fc3b3d28de231591ea5918a2956d3 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Mon, 10 Sep 2012 09:28:45 -0700 Subject: [PATCH 03/17] Fix zoom out keyboard shortcut for mac. --- web/viewer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/web/viewer.js b/web/viewer.js index 9b7d47496..c6a9766d8 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -2295,6 +2295,7 @@ window.addEventListener('keydown', function keydown(evt) { PDFView.zoomIn(); handled = true; break; + case 173: // FF/Mac '-' case 109: // FF '-' case 189: // Chrome '-' PDFView.zoomOut(); From 3fed93d80894befa9ae4ec42a45bc35c29ba5c59 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 11 Sep 2012 16:04:01 -0700 Subject: [PATCH 04/17] Adds text layer testing --- test/driver.js | 65 ++++++++++++++++++++++++++++++++++------- test/test.py | 7 +++-- test/test_manifest.json | 12 ++++++++ 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/test/driver.js b/test/driver.js index 54179f6cb..d1a8a17a7 100644 --- a/test/driver.js +++ b/test/driver.js @@ -26,7 +26,7 @@ // "firefox-bin: Fatal IO error 12 (Cannot allocate memory) on X server :1." // PDFJS.disableWorker = true; -var appPath, browser, canvas, currentTaskIdx, manifest, stdout; +var appPath, browser, canvas, dummyCanvas, currentTaskIdx, manifest, stdout; var inFlightRequests = 0; function queryParams() { @@ -148,6 +148,46 @@ function canvasToDataURL() { return canvas.toDataURL('image/png'); } +function NullTextLayerBuilder() { +} +NullTextLayerBuilder.prototype = { + beginLayout: function NullTextLayerBuilder_BeginLayout() {}, + endLayout: function NullTextLayerBuilder_EndLayout() {}, + appendText: function NullTextLayerBuilder_AppendText() {} +}; + +function SimpleTextLayerBuilder(ctx, viewport) { + this.ctx = ctx; + this.viewport = viewport; +} +SimpleTextLayerBuilder.prototype = { + beginLayout: function SimpleTextLayerBuilder_BeginLayout() { + this.ctx.save(); + }, + endLayout: function SimpleTextLayerBuilder_EndLayout() { + this.ctx.restore(); + }, + appendText: function SimpleTextLayerBuilder_AppendText(text, fontName, + fontSize) { + var ctx = this.ctx, viewport = this.viewport; + // vScale and hScale already contain the scaling to pixel units + var fontHeight = fontSize * text.geom.vScale; + ctx.beginPath(); + ctx.strokeStyle = 'red'; + ctx.fillStyle = 'yellow'; + ctx.rect(text.geom.x, text.geom.y - fontHeight, + text.canvasWidth * text.geom.hScale, fontHeight); + ctx.stroke(); + ctx.fill(); + + var textContent = bidi(text, -1); + ctx.font = fontHeight + 'px sans-serif'; + ctx.fillStyle = 'black'; + ctx.fillText(textContent, text.geom.x, text.geom.y); + } +}; + + function nextPage(task, loadError) { var failure = loadError || ''; @@ -196,16 +236,21 @@ function nextPage(task, loadError) { canvas.height = viewport.height; clear(ctx); - // using the text layer builder that does nothing to test - // text layer creation operations - var textLayerBuilder = { - beginLayout: function nullTextLayerBuilderBeginLayout() {}, - endLayout: function nullTextLayerBuilderEndLayout() {}, - appendText: function nullTextLayerBuilderAppendText(text, fontName, - fontSize) {} - }; + var drawContext, textLayerBuilder; + if (task.type == 'text') { + // using dummy canvas for pdf context drawing operations + if (!dummyCanvas) { + dummyCanvas = document.createElement('canvas'); + } + drawContext = dummyCanvas.getContext('2d'); + // ... text builder will draw its content on the test canvas + textLayerBuilder = new SimpleTextLayerBuilder(ctx, viewport); + } else { + drawContext = ctx; + textLayerBuilder = new NullTextLayerBuilder(); + } var renderContext = { - canvasContext: ctx, + canvasContext: drawContext, textLayer: textLayerBuilder, viewport: viewport }; diff --git a/test/test.py b/test/test.py index b5e3241b9..0e62aa9fe 100644 --- a/test/test.py +++ b/test/test.py @@ -514,7 +514,7 @@ def check(task, results, browser, masterMode): return kind = task['type'] - if 'eq' == kind: + if 'eq' == kind or 'text' == kind: checkEq(task, results, browser, masterMode) elif 'fbf' == kind: checkFBF(task, results, browser) @@ -528,6 +528,7 @@ def checkEq(task, results, browser, masterMode): pfx = os.path.join(REFDIR, sys.platform, browser, task['id']) results = results[0] taskId = task['id'] + taskType = task['type'] passed = True for page in xrange(len(results)): @@ -547,7 +548,7 @@ def checkEq(task, results, browser, masterMode): eq = (ref == snapshot) if not eq: - print 'TEST-UNEXPECTED-FAIL | eq', taskId, '| in', browser, '| rendering of page', page + 1, '!= reference rendering' + print 'TEST-UNEXPECTED-FAIL | ', taskType, taskId, '| in', browser, '| rendering of page', page + 1, '!= reference rendering' if not State.eqLog: State.eqLog = open(EQLOG_FILE, 'w') @@ -576,7 +577,7 @@ def checkEq(task, results, browser, masterMode): of.close() if passed: - print 'TEST-PASS | eq test', task['id'], '| in', browser + print 'TEST-PASS | ', taskType, ' test', task['id'], '| in', browser def checkFBF(task, results, browser): round0, round1 = results[0], results[1] diff --git a/test/test_manifest.json b/test/test_manifest.json index d19633947..e7575f41f 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -11,6 +11,12 @@ "rounds": 2, "type": "fbf" }, + { "id": "tracemonkey-text", + "file": "pdfs/tracemonkey.pdf", + "md5": "9a192d8b1a7dc652a19835f6f08098bd", + "rounds": 1, + "type": "text" + }, { "id": "html5-canvas-cheat-sheet-load", "file": "pdfs/canvas.pdf", "md5": "59510028561daf62e00bf9f6f066b033", @@ -89,6 +95,12 @@ "rounds": 1, "type": "eq" }, + { "id": "thuluthfont-text", + "file": "pdfs/ThuluthFeatures.pdf", + "md5": "b7e18bf7a3d6a9c82aefa12d721072fc", + "rounds": 1, + "type": "text" + }, { "id": "freeculture", "file": "pdfs/freeculture.pdf", "md5": "dcdf3a8268e6a18938a42d5149efcfca", From 9fba150dd214d4a14e5d9ebdf268202ddc6f3512 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 12 Sep 2012 17:31:04 -0700 Subject: [PATCH 05/17] Move font translation to the worker --- src/api.js | 19 +++++-------------- src/evaluator.js | 29 ++++++++++++++--------------- src/fonts.js | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/api.js b/src/api.js index d6d13a095..169faea0d 100644 --- a/src/api.js +++ b/src/api.js @@ -575,24 +575,15 @@ var WorkerTransport = (function WorkerTransportClosure() { this.objs.resolve(id, imageData); break; case 'Font': - var name = data[2]; - var file = data[3]; - var properties = data[4]; - - if (file) { - // Rewrap the ArrayBuffer in a stream. - var fontFileDict = new Dict(); - file = new Stream(file, 0, file.length, fontFileDict); - } + var exportedData = data[2]; // At this point, only the font object is created but the font is // not yet attached to the DOM. This is done in `FontLoader.bind`. var font; - try { - font = new Font(name, file, properties); - } catch (e) { - font = new ErrorFont(e); - } + if ('error' in exportedData) + font = new ErrorFont(exportedData.error); + else + font = new Font(exportedData); this.objs.resolve(id, font); break; default: diff --git a/src/evaluator.js b/src/evaluator.js index 621dd613f..704091149 100644 --- a/src/evaluator.js +++ b/src/evaluator.js @@ -171,31 +171,30 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { ++self.objIdCounter; if (!font.loadedName) { - font.translated = self.translateFont(font, xref, resources, - dependency); - if (font.translated) { + var translated = self.translateFont(font, xref, resources, + dependency); + if (translated) { // keep track of each font we translated so the caller can // load them asynchronously before calling display on a page loadedName = 'font_' + uniquePrefix + self.objIdCounter; - font.translated.properties.loadedName = loadedName; + translated.properties.loadedName = loadedName; font.loadedName = loadedName; + font.translated = translated; - var translated = font.translated; - // Convert the file to an ArrayBuffer which will be turned back into - // a Stream in the main thread. - if (translated.file) - translated.file = translated.file.getBytes(); - if (translated.properties.file) { - translated.properties.file = - translated.properties.file.getBytes(); + var data; + try { + var fontObj = new Font(translated.name, + translated.file, + translated.properties); + data = fontObj.export(); + } catch (e) { + data = { error: e }; } handler.send('obj', [ loadedName, 'Font', - translated.name, - translated.file, - translated.properties + data ]); } } diff --git a/src/fonts.js b/src/fonts.js index 15af2fa39..820ada8a0 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -1526,6 +1526,15 @@ function fontCharsToUnicode(charCodes, fontProperties) { */ var Font = (function FontClosure() { function Font(name, file, properties) { + if (arguments.length === 1) { + // importing translated data + var data = arguments[0]; + for (var i in data) { + this[i] = data[i]; + } + return; + } + this.name = name; this.coded = properties.coded; this.charProcOperatorList = properties.charProcOperatorList; @@ -2036,6 +2045,15 @@ var Font = (function FontClosure() { mimetype: null, encoding: null, + export: function Font_export() { + var data = {}; + for (var i in this) { + if (this.hasOwnProperty(i)) + data[i] = this[i]; + } + return data; + }, + checkAndRepair: function Font_checkAndRepair(name, font, properties) { function readTableEntry(file) { var tag = file.getBytes(4); From c8144d683d23e88ac469448c66923ffb2fde81c2 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 13 Sep 2012 09:33:50 -0700 Subject: [PATCH 06/17] Mozilla central change for metro. --- extensions/firefox/components/PdfStreamConverter.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/firefox/components/PdfStreamConverter.js b/extensions/firefox/components/PdfStreamConverter.js index a313766f4..76b7788a8 100644 --- a/extensions/firefox/components/PdfStreamConverter.js +++ b/extensions/firefox/components/PdfStreamConverter.js @@ -32,6 +32,7 @@ const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html'; const MAX_DATABASE_LENGTH = 4096; const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}'; const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}'; +const METRO_ID = '{99bceaaa-e3c6-48c1-b981-ef9b46b67d60}'; Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Services.jsm'); @@ -50,7 +51,8 @@ if (appInfo.ID === FIREFOX_ID) { privateBrowsing = Cc['@mozilla.org/privatebrowsing;1'] .getService(Ci.nsIPrivateBrowsingService); inPrivateBrowsing = privateBrowsing.privateBrowsingEnabled; -} else if (appInfo.ID === SEAMONKEY_ID) { +} else if (appInfo.ID === SEAMONKEY_ID || + appInfo.ID === METRO_ID) { privateBrowsing = null; inPrivateBrowsing = false; } From e086cf36f4d9d7f021b218de77edefde60ab5214 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 13 Sep 2012 08:09:46 -0700 Subject: [PATCH 07/17] Refactor text extraction / font loading logic --- src/canvas.js | 14 ++--- src/evaluator.js | 131 ++++++++++++++++++++++------------------------- src/fonts.js | 72 +++++++++----------------- web/viewer.js | 25 ++++----- 4 files changed, 98 insertions(+), 144 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index e5a204cb7..cca2c9212 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -782,15 +782,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { x += charWidth; var glyphUnicode = glyph.unicode === ' ' ? '\u00A0' : glyph.unicode; - var glyphUnicodeLength = glyphUnicode.length; - //reverse an arabic ligature - if (glyphUnicodeLength > 1 && - isRTLRangeFor(glyphUnicode.charCodeAt(0))) { - for (var ii = glyphUnicodeLength - 1; ii >= 0; ii--) - text.str += glyphUnicode[ii]; - } else - text.str += glyphUnicode; - text.length += glyphUnicodeLength; + if (glyphUnicode in NormalizedUnicodes) + glyphUnicode = NormalizedUnicodes[glyphUnicode]; + text.str += reverseIfRtl(glyphUnicode); text.canvasWidth += charWidth; } current.x += x * textHScale2; @@ -842,7 +836,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var numFakeSpaces = Math.round(-e / text.geom.spaceWidth); if (numFakeSpaces > 0) { text.str += '\u00A0'; - text.length++; } } } @@ -856,7 +849,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { text.str += shownText.str; } text.canvasWidth += shownText.canvasWidth; - text.length += shownText.length; } } else { error('TJ array element ' + e + ' is not string or num'); diff --git a/src/evaluator.js b/src/evaluator.js index 704091149..59fec61a6 100644 --- a/src/evaluator.js +++ b/src/evaluator.js @@ -26,6 +26,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { this.handler = handler; this.uniquePrefix = uniquePrefix; this.objIdCounter = 0; + this.fontIdCounter = 0; } var OP_MAP = { @@ -138,6 +139,35 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { }; PartialEvaluator.prototype = { + loadFont: function PartialEvaluator_loadFont(fontName, font, xref, + resources, dependency) { + var fontRes = resources.get('Font'); + + assert(fontRes, 'fontRes not available'); + + font = xref.fetchIfRef(font) || fontRes.get(fontName); + assertWellFormed(isDict(font)); + + ++this.fontIdCounter; + var loadedName = font.loadedName; + if (!loadedName) { + // keep track of each font we translated so the caller can + // load them asynchronously before calling display on a page + loadedName = 'font_' + this.uniquePrefix + this.fontIdCounter; + font.loadedName = loadedName; + + var translated; + try { + translated = this.translateFont(font, xref, resources, + dependency); + } catch (e) { + translated = { error: e }; + } + font.translated = translated; + } + return font; + }, + getOperatorList: function PartialEvaluator_getOperatorList(stream, resources, dependency, @@ -160,45 +190,35 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { } function handleSetFont(fontName, font) { - var loadedName = null; + font = self.loadFont(fontName, font, xref, resources, dependency); - var fontRes = resources.get('Font'); + var loadedName = font.loadedName; + if (!font.sent) { + var data = font.translated; + if (data.loadCharProcs) { + delete data.loadCharProcs; - assert(fontRes, 'fontRes not available'); - - font = xref.fetchIfRef(font) || fontRes.get(fontName); - assertWellFormed(isDict(font)); - - ++self.objIdCounter; - if (!font.loadedName) { - var translated = self.translateFont(font, xref, resources, - dependency); - if (translated) { - // keep track of each font we translated so the caller can - // load them asynchronously before calling display on a page - loadedName = 'font_' + uniquePrefix + self.objIdCounter; - translated.properties.loadedName = loadedName; - font.loadedName = loadedName; - font.translated = translated; - - var data; - try { - var fontObj = new Font(translated.name, - translated.file, - translated.properties); - data = fontObj.export(); - } catch (e) { - data = { error: e }; + var charProcs = font.get('CharProcs').getAll(); + var fontResources = font.get('Resources') || resources; + var charProcOperatorList = {}; + for (var key in charProcs) { + var glyphStream = charProcs[key]; + charProcOperatorList[key] = + self.getOperatorList(glyphStream, fontResources, dependency); } - - handler.send('obj', [ - loadedName, - 'Font', - data - ]); + data.charProcOperatorList = charProcOperatorList; } + + if (data instanceof Font) + data = data.export(); + + handler.send('obj', [ + loadedName, + 'Font', + data + ]); + font.sent = true; } - loadedName = loadedName || font.loadedName; // Ensure the font is ready before the font is set // and later on used for drawing. @@ -491,20 +511,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { var xref = this.xref; function handleSetFont(fontName, fontRef) { - var fontRes = resources.get('Font'); - - // TODO: TOASK: Is it possible to get here? If so, what does - // args[0].name should be like??? - assert(fontRes, 'fontRes not available'); - - fontRes = xref.fetchIfRef(fontRes); - fontRef = fontRef || fontRes.get(fontName); - var font = xref.fetchIfRef(fontRef), tra; - assertWellFormed(isDict(font)); - if (!font.translated) { - font.translated = self.translateFont(font, xref, resources); - } - return font; + return self.loadFont(fontName, fontRef, xref, resources, null); } resources = xref.fetchIfRef(resources) || new Dict(); @@ -546,7 +553,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { break; } // switch if (chunk !== '') { - text += fontCharsToUnicode(chunk, font.translated.properties); + text += fontCharsToUnicode(chunk, font.translated); chunk = ''; } @@ -853,7 +860,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { // - get the FontDescriptor from the descendant font var df = dict.get('DescendantFonts'); if (!df) - return null; + error('Descendant fonts are not specified'); dict = isArray(df) ? xref.fetchIfRef(df[0]) : df; @@ -876,7 +883,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { // This case is here for compatibility. var baseFontName = dict.get('BaseFont'); if (!isName(baseFontName)) - return null; + error('Base font is not specified'); // Using base font name as a font name. baseFontName = baseFontName.name.replace(/[,_]/g, '-'); @@ -899,11 +906,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { }; this.extractDataStructures(dict, dict, xref, properties); - return { - name: baseFontName, - dict: baseDict, - properties: properties - }; + return new Font(baseFontName, null, properties); } } @@ -939,6 +942,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { file: fontFile, length1: length1, length2: length2, + loadedName: baseDict.loadedName, composite: composite, wideChars: composite, fixedPitch: false, @@ -959,22 +963,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { if (type.name === 'Type3') { properties.coded = true; - var charProcs = dict.get('CharProcs').getAll(); - var fontResources = dict.get('Resources') || resources; - properties.charProcOperatorList = {}; - for (var key in charProcs) { - var glyphStream = charProcs[key]; - properties.charProcOperatorList[key] = - this.getOperatorList(glyphStream, fontResources, dependency); - } } - return { - name: fontName.name, - dict: baseDict, - file: fontFile, - properties: properties - }; + return new Font(fontName.name, fontFile, properties); } }; diff --git a/src/fonts.js b/src/fonts.js index 820ada8a0..7707bffb6 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -1464,54 +1464,30 @@ var NormalizedUnicodes = { '\uFE4F': '\u005F' }; -function fontCharsToUnicode(charCodes, fontProperties) { - var toUnicode = fontProperties.toUnicode; - var composite = fontProperties.composite; - var encoding, differences, cidToUnicode; - var result = ''; - if (composite) { - cidToUnicode = fontProperties.cidToUnicode; - for (var i = 0, ii = charCodes.length; i < ii; i += 2) { - var charCode = (charCodes.charCodeAt(i) << 8) | - charCodes.charCodeAt(i + 1); - if (toUnicode && charCode in toUnicode) { - var unicode = toUnicode[charCode]; - result += typeof unicode !== 'number' ? unicode : - String.fromCharCode(unicode); - continue; - } - result += String.fromCharCode(!cidToUnicode ? charCode : - cidToUnicode[charCode] || charCode); - } - } else { - differences = fontProperties.differences; - encoding = fontProperties.baseEncoding; - for (var i = 0, ii = charCodes.length; i < ii; i++) { - var charCode = charCodes.charCodeAt(i); - var unicode; - if (toUnicode && charCode in toUnicode) { - var unicode = toUnicode[charCode]; - result += typeof unicode !== 'number' ? unicode : - String.fromCharCode(unicode); - continue; - } +function reverseIfRtl(chars) { + var charsLength = chars.length; + //reverse an arabic ligature + if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) + return chars; - var glyphName = charCode in differences ? differences[charCode] : - encoding[charCode]; - if (glyphName in GlyphsUnicode) { - result += String.fromCharCode(GlyphsUnicode[glyphName]); - continue; - } - result += String.fromCharCode(charCode); - } - } - // normalizing the unicode characters - for (var i = 0, ii = result.length; i < ii; i++) { - if (!(result[i] in NormalizedUnicodes)) + var s = ''; + for (var ii = charsLength - 1; ii >= 0; ii--) + s += chars[ii]; + return s; +} + +function fontCharsToUnicode(charCodes, font) { + var glyphs = font.charsToGlyphs(charCodes); + var result = ''; + for (var i = 0, ii = glyphs.length; i < ii; i++) { + var glyph = glyphs[i]; + if (!glyph) continue; - result = result.substring(0, i) + NormalizedUnicodes[result[i]] + - result.substring(i + 1); - ii = result.length; + + var glyphUnicode = glyph.unicode; + if (glyphUnicode in NormalizedUnicodes) + glyphUnicode = NormalizedUnicodes[glyphUnicode]; + result += reverseIfRtl(glyphUnicode); } return result; } @@ -1536,8 +1512,9 @@ var Font = (function FontClosure() { } this.name = name; + this.loadedName = properties.loadedName; this.coded = properties.coded; - this.charProcOperatorList = properties.charProcOperatorList; + this.loadCharProcs = properties.coded; this.sizes = []; var names = name.split('+'); @@ -1641,7 +1618,6 @@ var Font = (function FontClosure() { this.widthMultiplier = !properties.fontMatrix ? 1.0 : 1.0 / properties.fontMatrix[0]; this.encoding = properties.baseEncoding; - this.loadedName = properties.loadedName; this.loading = true; }; diff --git a/web/viewer.js b/web/viewer.js index 2fe30debe..bf2c44012 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1844,22 +1844,18 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { return; } var textDiv = textDivs.shift(); - if (textDiv.dataset.textLength > 0) { - textLayerDiv.appendChild(textDiv); + textLayerDiv.appendChild(textDiv); - if (textDiv.dataset.textLength > 1) { // avoid div by zero - // Adjust div width to match canvas text + ctx.font = textDiv.style.fontSize + ' sans-serif'; + var width = ctx.measureText(textDiv.textContent).width; - ctx.font = textDiv.style.fontSize + ' sans-serif'; - var width = ctx.measureText(textDiv.textContent).width; + if (width > 0) { + var textScale = textDiv.dataset.canvasWidth / width; - var textScale = textDiv.dataset.canvasWidth / width; - - CustomStyle.setProp('transform' , textDiv, - 'scale(' + textScale + ', 1)'); - CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%'); - } - } // textLength > 0 + CustomStyle.setProp('transform' , textDiv, + 'scale(' + textScale + ', 1)'); + CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%'); + } } renderTimer = setInterval(renderTextLayer, renderInterval); @@ -1899,7 +1895,6 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { textDiv.style.top = (text.geom.y - fontHeight) + 'px'; textDiv.textContent = PDFJS.bidi(text, -1); textDiv.dir = text.direction; - textDiv.dataset.textLength = text.length; this.textDivs.push(textDiv); }; }; @@ -2068,7 +2063,7 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) { }); document.getElementById('searchTermsInput').addEventListener('keydown', - function() { + function(event) { if (event.keyCode == 13) { PDFView.search(); } From 38bb3b488026ceef03f437fd6eba6da9098c32fa Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 13 Sep 2012 16:45:56 -0700 Subject: [PATCH 08/17] Removing font loading hack from MOZCENTRAL --- src/fonts.js | 55 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/src/fonts.js b/src/fonts.js index 820ada8a0..fa61c4b61 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -418,11 +418,26 @@ function mapPrivateUseChars(code) { } var FontLoader = { +//#if !(MOZCENTRAL) loadingContext: { requests: [], nextRequestId: 0 }, + isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() { + if (isWorker) + return false; + + // User agent string sniffing is bad, but there is no reliable way to tell + // if font is fully loaded and ready to be used with canvas. + var userAgent = window.navigator.userAgent; + var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent); + if (m && m[1] >= 14) + return true; + // TODO other browsers + return false; + })(), + bind: function fontLoaderBind(fonts, callback) { assert(!isWorker, 'bind() shall be called from main thread'); @@ -437,23 +452,15 @@ var FontLoader = { } font.attached = true; - var str = ''; - var data = font.data; - if (data) { - var length = data.length; - for (var j = 0; j < length; j++) - str += String.fromCharCode(data[j]); - - var rule = font.bindDOM(str); - if (rule) { - rules.push(rule); - fontsToLoad.push(font); - } + var rule = font.bindDOM(); + if (rule) { + rules.push(rule); + fontsToLoad.push(font); } } var request = FontLoader.queueLoadingCallback(callback); - if (rules.length > 0) { + if (rules.length > 0 && !this.isSyncFontLoadingSupported) { FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request); } else { request.complete(); @@ -595,6 +602,22 @@ var FontLoader = { document.body.appendChild(frame); /** Hack end */ } +//#else +//bind: function fontLoaderBind(fonts, callback) { +// assert(!isWorker, 'bind() shall be called from main thread'); +// +// for (var i = 0, ii = fonts.length; i < ii; i++) { +// var font = fonts[i]; +// if (font.attached) +// continue; +// +// font.attached = true; +// font.bindDOM() +// } +// +// setTimeout(callback); +//} +//#endif }; var UnicodeRanges = [ @@ -3156,7 +3179,11 @@ var Font = (function FontClosure() { } }, - bindDOM: function Font_bindDOM(data) { + bindDOM: function Font_bindDOM() { + if (!this.data) + return null; + + var data = bytesToString(this.data); var fontName = this.loadedName; // Add the font-face rule to the document From d9b8cb84f85ae0d9c4d76e19febab48f45e0291d Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 14 Sep 2012 09:25:00 -0700 Subject: [PATCH 09/17] Update index template. --- web/index.html.template | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/web/index.html.template b/web/index.html.template index 44e9a0cbe..118b7362f 100644 --- a/web/index.html.template +++ b/web/index.html.template @@ -8,7 +8,8 @@