From 9fe5eff90560948915b9fde24068e6168b963b40 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Mon, 13 Feb 2012 17:35:58 -0800 Subject: [PATCH 1/9] Combining Yury's and my debugging tools. --- Makefile | 1 + src/canvas.js | 8 +- src/core.js | 8 +- src/debugger.js | 397 +++++++++++++++++++++++++++++++++++++++++++ src/fonts.js | 3 + src/worker_loader.js | 3 +- web/viewer.css | 37 ++++ web/viewer.html | 1 + web/viewer.js | 14 ++ 9 files changed, 469 insertions(+), 3 deletions(-) create mode 100644 src/debugger.js diff --git a/Makefile b/Makefile index 043cb7fb5..4cc370944 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,7 @@ PDF_JS_FILES = \ pattern.js \ stream.js \ worker.js \ + debugger.js \ ../external/jpgjs/jpg.js \ jpx.js \ $(NULL) diff --git a/src/canvas.js b/src/canvas.js index f4815a655..d778fd597 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -265,7 +265,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { }, executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR, - executionStartIdx, continueCallback) { + executionStartIdx, continueCallback, + stepper) { var argsArray = codeIR.argsArray; var fnArray = codeIR.fnArray; var i = executionStartIdx || 0; @@ -284,6 +285,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var slowCommands = this.slowCommands; while (true) { + if (stepper !== null && i === stepper.nextBreakPoint) { + stepper.breakIt(i, continueCallback); + return i; + } + fnName = fnArray[i]; if (fnName !== 'dependency') { diff --git a/src/core.js b/src/core.js index ae0f97231..acd015644 100644 --- a/src/core.js +++ b/src/core.js @@ -244,10 +244,16 @@ var Page = (function PageClosure() { var startIdx = 0; var length = this.IRQueue.fnArray.length; var IRQueue = this.IRQueue; + var stepper = null; + if (PDFJS.pdfBug && Debugger.enabled) { + stepper = Debugger.create(this.pageNumber); + stepper.init(IRQueue); + stepper.nextBreakPoint = stepper.getNextBreakPoint(); + } var self = this; function next() { - startIdx = gfx.executeIRQueue(IRQueue, startIdx, next); + startIdx = gfx.executeIRQueue(IRQueue, startIdx, next, stepper); if (startIdx == length) { self.stats.render = Date.now(); gfx.endDrawing(); diff --git a/src/debugger.js b/src/debugger.js new file mode 100644 index 000000000..6bc993c0b --- /dev/null +++ b/src/debugger.js @@ -0,0 +1,397 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + +'use strict'; + +var FontInspector = (function FontInspectorClosure() { + var fonts; + var panelWidth = 300; + var active = false; + function removeSelection() { + var divs = document.getElementsByTagName('div'); + for (var i = 0; i < divs.length; ++i) { + var div = divs[i], style = div.getAttribute('style'); + if (!style || style.indexOf('pdfFont') < 0) continue; + var m = /(pdfFont\d+)/.exec(style); + div.dataset.fontName = ''; + div.className = ''; + } + } + function resetSelection() { + var divs = document.getElementsByTagName('div'); + for (var i = 0; i < divs.length; ++i) { + var div = divs[i], style = div.getAttribute('style'); + if (!style || style.indexOf('pdfFont') < 0) continue; + var m = /(pdfFont\d+)/.exec(style); + div.dataset.fontName = m[1]; + div.className = 'debuggerHideText'; + } + } + function selectFont(fontName, show) { + var divs = document.getElementsByTagName('div'); + for (var i = 0; i < divs.length; ++i) { + var div = divs[i], style = div.getAttribute('style'); + if (div.dataset.fontName != fontName) continue; + div.className = show ? 'debuggerShowText' : 'debuggerHideText'; + } + } + function textLayerClick(e) { + if (!e.target.dataset.fontName || e.target.tagName != 'DIV') + return; + var fontName = e.target.dataset.fontName; + var selects = document.getElementsByTagName('input'); + for (var i = 0; i < selects.length; ++i) { + var select = selects[i]; + if (select.dataset.fontName != fontName) continue; + select.checked = !select.checked; + selectFont(fontName, select.checked); + select.scrollIntoView(); + } + } + return { + id: 'FontInspector', + name: 'Font Inspector', + panel: null, + manager: null, + init: function init() { + var panel = this.panel; + panel.setAttribute('style', 'padding: 5px;'); + var tmp = document.createElement('button'); + tmp.addEventListener('click', resetSelection); + tmp.textContent = 'Refresh'; + panel.appendChild(tmp); + + fonts = document.createElement('div'); + panel.appendChild(fonts); + }, + enabled: false, + get active() { + return active; + }, + set active(value) { + active = value; + if (active) { + document.body.addEventListener('click', textLayerClick, true); + resetSelection(); + } else { + document.body.removeEventListener('click', textLayerClick); + removeSelection(); + } + }, + fontAdded: function fontAdded(fontObj, url) { + function properties(obj, list) { + var moreInfo = document.createElement('table'); + for (var i = 0; i < list.length; i++) { + var tr = document.createElement('tr'); + var td1 = document.createElement('td'); + td1.textContent = list[i]; + tr.appendChild(td1); + var td2 = document.createElement('td'); + td2.textContent = obj[list[i]].toString(); + tr.appendChild(td2); + moreInfo.appendChild(tr); + } + return moreInfo; + } + var moreInfo = properties(fontObj, ['name', 'type']); + var m = /url\(['"]?([^\)"']+)/.exec(url); + var fontName = fontObj.loadedName; + var font = document.createElement('div'); + var name = document.createElement('span'); + name.textContent = fontName; + var download = document.createElement('a'); + download.href = m[1]; + download.textContent = 'Download'; + var logIt = document.createElement('a'); + logIt.href = ''; + logIt.textContent = 'Log'; + logIt.addEventListener('click', function(event) { + event.preventDefault(); + console.log(fontObj); + }); + var select = document.createElement('input'); + select.setAttribute('type', 'checkbox'); + select.dataset.fontName = fontName; + select.addEventListener('click', (function(select, fontName) { + return (function() { + selectFont(fontName, select.checked); + }); + })(select, fontName)); + font.appendChild(select); + font.appendChild(name); + font.appendChild(document.createTextNode(' ')); + font.appendChild(download); + font.appendChild(document.createTextNode(' ')); + font.appendChild(logIt); + font.appendChild(moreInfo); + fonts.appendChild(font); + // Somewhat of a hack, shoudl probably add a hook for when the text layer + // is done rendering. + setTimeout(function() { + if (this.active) + resetSelection(); + }.bind(this), 2000); + } + }; +})(); + +// Manages all the page steppers. +var Debugger = (function PdfDeuggerClosure() { + var steppers = []; + var stepperDiv = null; + var stepperControls = null; + var stepperChooser = null; + var breakPoints = {}; + return { + id: 'Debugger', + name: 'Debugger', + panel: null, + manager: null, + init: function init() { + var self = this; + this.panel.setAttribute('style', 'padding: 5px;'); + stepperControls = document.createElement('div'); + stepperChooser = document.createElement('select'); + stepperChooser.addEventListener('change', function(event) { + self.selectStepper(this.value); + }); + stepperControls.appendChild(stepperChooser); + stepperDiv = document.createElement('div'); + this.panel.appendChild(stepperControls); + this.panel.appendChild(stepperDiv); + if (sessionStorage.getItem('pdfjsBreakPoints')) + breakPoints = JSON.parse(sessionStorage.getItem('pdfjsBreakPoints')); + }, + enabled: false, + active: false, + create: function create(pageNumber) { + var debug = document.createElement('div'); + debug.id = 'stepper' + pageNumber; + debug.setAttribute('hidden', true); + debug.className = 'stepper'; + stepperDiv.appendChild(debug); + var b = document.createElement('option'); + b.textContent = 'Page ' + (pageNumber + 1); + b.value = pageNumber; + stepperChooser.appendChild(b); + var initBreakPoints = breakPoints[pageNumber] || []; + var pdfDebuggerStepper = new DebuggerStepper(debug, pageNumber, + initBreakPoints); + steppers.push(pdfDebuggerStepper); + if (steppers.length === 1) + this.selectStepper(pageNumber, false); + return pdfDebuggerStepper; + }, + selectStepper: function selectStepper(pageNumber, selectPanel) { + if (selectPanel) + this.manager.selectPanel(1); + for (var i = 0; i < steppers.length; ++i) { + var stepper = steppers[i]; + if (stepper.pageNumber == pageNumber) + stepper.panel.removeAttribute('hidden'); + else + stepper.panel.setAttribute('hidden', true); + } + }, + saveBreakPoints: function saveBreakPoints(pageNumber, bps) { + breakPoints[pageNumber] = bps; + sessionStorage.setItem('pdfjsBreakPoints', JSON.stringify(breakPoints)); + } + }; +})(); + +// The stepper for each page's IRQueue. +var DebuggerStepper = (function DebuggerStepperClosure() { + function DebuggerStepper(panel, pageNumber, initialBreakPoints) { + this.panel = panel; + this.len; + this.breakPoint = 0; + this.nextBreakPoint = null; + this.pageNumber = pageNumber; + this.breakPoints = initialBreakPoints; + this.currentIdx = -1; + } + DebuggerStepper.prototype = { + init: function init(IRQueue) { + function c(tag, textContent) { + var d = document.createElement(tag); + if (textContent) + d.textContent = textContent; + return d; + } + var panel = this.panel; + this.len = IRQueue.fnArray.length; + var content = c('div', 'c=contine, s=step'); + var table = c('table'); + content.appendChild(table); + table.cellSpacing = 0; + var headerRow = c('tr'); + table.appendChild(headerRow); + headerRow.appendChild(c('th', 'Break')); + headerRow.appendChild(c('th', 'Idx')); + headerRow.appendChild(c('th', 'fn')); + headerRow.appendChild(c('th', 'args')); + + for (var i = 0; i < IRQueue.fnArray.length; i++) { + var line = c('tr'); + line.className = 'line'; + line.id = 'idx' + i; + table.appendChild(line); + var checked = this.breakPoints.indexOf(i) != -1; + var args = IRQueue.argsArray[i] ? IRQueue.argsArray[i] : []; + + var breakCell = c('td'); + var cbox = c('input'); + cbox.type = 'checkbox'; + cbox.className = 'points'; + cbox.checked = checked; + var self = this; + cbox.onclick = (function(x) { + return function() { + if (this.checked) + self.breakPoints.push(x); + else + self.breakPoints.splice(self.breakPoints.indexOf(x), 1); + Debugger.saveBreakPoints(self.pageNumber, self.breakPoints); + } + })(i); + + breakCell.appendChild(cbox); + line.appendChild(breakCell); + line.appendChild(c('td', i.toString())); + line.appendChild(c('td', IRQueue.fnArray[i])); + line.appendChild(c('td', args.join(', '))); + } + panel.appendChild(content); + var self = this; + }, + getNextBreakPoint: function getNextBreakPoint() { + this.breakPoints.sort(function(a, b) { return a - b; }); + for (var i = 0; i < this.breakPoints.length; i++) { + if (this.breakPoints[i] > this.currentIdx) + return this.breakPoints[i]; + } + return null; + }, + breakIt: function breakIt(idx, callback) { + Debugger.selectStepper(this.pageNumber, true); + var self = this; + var dom = document; + self.currentIdx = idx; + var listener = function(e) { + switch (e.keyCode) { + case 83: // step + dom.removeEventListener('keydown', listener, false); + self.nextBreakPoint = self.currentIdx + 1; + self.goTo(-1); + callback(); + break; + case 67: // continue + dom.removeEventListener('keydown', listener, false); + var breakPoint = self.getNextBreakPoint(); + self.nextBreakPoint = breakPoint; + self.goTo(-1); + callback(); + break; + } + } + dom.addEventListener('keydown', listener, false); + self.goTo(idx); + }, + goTo: function goTo(idx) { + var allRows = this.panel.getElementsByClassName('line'); + for (var x = 0; x < allRows.length; x++) { + allRows[x].style.backgroundColor = null; + } + var row = document.getElementById('idx' + idx); + if (row) { + row.style.backgroundColor = 'rgb(251,250,207)'; + row.scrollIntoView(); + } + } + }; + return DebuggerStepper; +})(); + +// Manages all the debugging tools. +var PDFBug = (function PDFBugClosure() { + var panelWidth = 300; + var buttons = []; + var activePanel = null; + + return { + tools: [ + FontInspector, + Debugger + ], + init: function init() { + /* + * Basic Layout: + * Debugger + * Controls + * Panels + * Panel + * Panel + * ... + */ + var ui = document.createElement('div'); + ui.id = 'debugger'; + + var controls = document.createElement('div'); + controls.setAttribute('class', 'controls'); + ui.appendChild(controls); + + var panels = document.createElement('div'); + panels.setAttribute('class', 'panels'); + ui.appendChild(panels); + + document.body.appendChild(ui); + document.body.style.paddingRight = panelWidth + 'px'; + + // Initialize all the debugging tools. + var tools = this.tools; + for (var i = 0; i < tools.length; ++i) { + var tool = tools[i]; + var panel = document.createElement('div'); + var panelButton = document.createElement('button'); + panelButton.textContent = tool.name; + var self = this; + panelButton.addEventListener('click', (function(selected) { + return function(event) { + event.preventDefault(); + self.selectPanel(selected); + }; + })(i)); + controls.appendChild(panelButton); + panels.appendChild(panel); + tool.panel = panel; + tool.manager = this; + if (tool.enabled) + tool.init(); + else + panel.textContent = tool.name + ' is disabled. To enable add ' + + ' PDFBug_' + tool.id + '=true to the url query ' + + 'parameters and refresh.'; + buttons.push(panelButton); + } + this.selectPanel(0); + }, + selectPanel: function selectPanel(index) { + if (index === activePanel) + return; + activePanel = index; + var tools = this.tools; + for (var j = 0; j < tools.length; ++j) { + if (j == index) { + buttons[j].setAttribute('class', 'active'); + tools[j].active = true; + tools[j].panel.removeAttribute('hidden'); + } else { + buttons[j].setAttribute('class', ''); + tools[j].active = false; + tools[j].panel.setAttribute('hidden', 'true'); + } + } + } + }; +})(); diff --git a/src/fonts.js b/src/fonts.js index f8ae7de4c..cc754773f 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -2170,6 +2170,9 @@ var Font = (function FontClosure() { var styleSheet = styleElement.sheet; styleSheet.insertRule(rule, styleSheet.cssRules.length); + if (PDFJS.pdfBug && FontInspector.enabled) + FontInspector.fontAdded(this, url); + return rule; }, diff --git a/src/worker_loader.js b/src/worker_loader.js index fc3d7a5f7..c3edc9928 100644 --- a/src/worker_loader.js +++ b/src/worker_loader.js @@ -24,7 +24,8 @@ var files = [ 'stream.js', 'worker.js', '../external/jpgjs/jpg.js', - 'jpx.js' + 'jpx.js', + 'debugger.js' ]; // Load all the files. diff --git a/web/viewer.css b/web/viewer.css index 681e5046a..1d773b7d8 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -383,3 +383,40 @@ canvas { margin: 100px 0; text-align: center; } + +#debugger { + font-size: 10px; + position: fixed; + top: 35px; + bottom: 5px; + right: 2px; + width: 300px; + background: white; + border: 1px solid #666; + padding: 0; +} +#debugger .controls { + border-bottom: 1px solid #666; + padding: 3px; + background: -moz-linear-gradient(center bottom, #eee 0%, #fff 100%); +} +#debugger .panels { + overflow: auto; + position: absolute; + top: 27px; + left: 0; + right: 0; + bottom: 0; +} +#debugger button.active { + font-weight: bold; +} +.debuggerShowText { + background: yellow; + color: blue; + opacity: 0.3; +} +.debuggerHideText:hover { + background: yellow; + opacity: 0.3; +} \ No newline at end of file diff --git a/web/viewer.html b/web/viewer.html index 7c55ec735..a70737cff 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -29,6 +29,7 @@ + diff --git a/web/viewer.js b/web/viewer.js index 5a1a1df03..eaca39e77 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1119,6 +1119,20 @@ window.addEventListener('load', function webViewerLoad(evt) { if ('disableTextLayer' in params) PDFJS.disableTextLayer = (params['disableTextLayer'] === 'true'); + if ('PDFBug' in params) + PDFJS.pdfBug = (params['PDFBug'] === 'true'); + + if (PDFJS.pdfBug) { + var debugTools = PDFBug.tools; + for (var i = 0; i < debugTools.length; ++i) { + var tool = debugTools[i]; + var key = 'PDFBug_' + tool.id; + if (key in params) + tool.enabled = (params[key] === 'true'); + } + PDFBug.init(); + } + var sidebarScrollView = document.getElementById('sidebarScrollView'); sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true); }, true); From 6aa72f411b37897319d93ca7b33ecf581c639693 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Tue, 14 Feb 2012 09:24:29 -0800 Subject: [PATCH 2/9] Add a few comments. --- src/debugger.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/debugger.js b/src/debugger.js index 6bc993c0b..c5fc02aca 100644 --- a/src/debugger.js +++ b/src/debugger.js @@ -49,6 +49,7 @@ var FontInspector = (function FontInspectorClosure() { } } return { + // Poperties/functions needed by PDFBug. id: 'FontInspector', name: 'Font Inspector', panel: null, @@ -78,6 +79,7 @@ var FontInspector = (function FontInspectorClosure() { removeSelection(); } }, + // FontInspector specific functions. fontAdded: function fontAdded(fontObj, url) { function properties(obj, list) { var moreInfo = document.createElement('table'); @@ -125,7 +127,7 @@ var FontInspector = (function FontInspectorClosure() { font.appendChild(logIt); font.appendChild(moreInfo); fonts.appendChild(font); - // Somewhat of a hack, shoudl probably add a hook for when the text layer + // Somewhat of a hack, should probably add a hook for when the text layer // is done rendering. setTimeout(function() { if (this.active) @@ -136,13 +138,14 @@ var FontInspector = (function FontInspectorClosure() { })(); // Manages all the page steppers. -var Debugger = (function PdfDeuggerClosure() { +var Debugger = (function DeuggerClosure() { var steppers = []; var stepperDiv = null; var stepperControls = null; var stepperChooser = null; var breakPoints = {}; return { + // Poperties/functions needed by PDFBug. id: 'Debugger', name: 'Debugger', panel: null, @@ -164,6 +167,7 @@ var Debugger = (function PdfDeuggerClosure() { }, enabled: false, active: false, + // Debugger specific functions. create: function create(pageNumber) { var debug = document.createElement('div'); debug.id = 'stepper' + pageNumber; From ebf26a5e29ee17c602d7f15413dcd85c099e5738 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Tue, 14 Feb 2012 10:25:53 -0800 Subject: [PATCH 3/9] Fix undefined stepper. --- src/canvas.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/canvas.js b/src/canvas.js index d778fd597..67eb83c1d 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -285,7 +285,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var slowCommands = this.slowCommands; while (true) { - if (stepper !== null && i === stepper.nextBreakPoint) { + if (stepper && i === stepper.nextBreakPoint) { stepper.breakIt(i, continueCallback); return i; } From f54486d8c84827f6baa308ce8ae7d379a5eca7fb Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 15 Feb 2012 13:13:07 -0800 Subject: [PATCH 4/9] Change how the tools are enabled. --- src/debugger.js | 4 ++-- web/viewer.js | 17 ++++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/debugger.js b/src/debugger.js index c5fc02aca..372ebd68f 100644 --- a/src/debugger.js +++ b/src/debugger.js @@ -374,8 +374,8 @@ var PDFBug = (function PDFBugClosure() { tool.init(); else panel.textContent = tool.name + ' is disabled. To enable add ' + - ' PDFBug_' + tool.id + '=true to the url query ' + - 'parameters and refresh.'; + ' "' + tool.id + '" to the pdfBug parameter ' + + 'and refresh (seperate multiple by commas).'; buttons.push(panelButton); } this.selectPanel(0); diff --git a/web/viewer.js b/web/viewer.js index 46665fd87..5381f69c1 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1122,16 +1122,19 @@ window.addEventListener('load', function webViewerLoad(evt) { if ('disableTextLayer' in params) PDFJS.disableTextLayer = (params['disableTextLayer'] === 'true'); - if ('PDFBug' in params) - PDFJS.pdfBug = (params['PDFBug'] === 'true'); - - if (PDFJS.pdfBug) { + if ('pdfBug' in params) { + PDFJS.pdfBug = true; + var pdfBug = params['pdfBug']; + var all = false, enabled = []; + if (pdfBug === 'all') + all = true; + else + enabled = pdfBug.split(','); var debugTools = PDFBug.tools; for (var i = 0; i < debugTools.length; ++i) { var tool = debugTools[i]; - var key = 'PDFBug_' + tool.id; - if (key in params) - tool.enabled = (params[key] === 'true'); + if (all || enabled.indexOf(tool.id) !== -1) + tool.enabled = true; } PDFBug.init(); } From c04ab5fe45763989fb32a5d77fff4b9aaa36b484 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 15 Feb 2012 14:12:58 -0800 Subject: [PATCH 5/9] Change name of debugger to stepper. --- src/core.js | 4 ++-- src/debugger.js | 33 ++++++++++++++++----------------- web/viewer.css | 8 ++++---- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/core.js b/src/core.js index acd015644..3482f225b 100644 --- a/src/core.js +++ b/src/core.js @@ -245,8 +245,8 @@ var Page = (function PageClosure() { var length = this.IRQueue.fnArray.length; var IRQueue = this.IRQueue; var stepper = null; - if (PDFJS.pdfBug && Debugger.enabled) { - stepper = Debugger.create(this.pageNumber); + if (PDFJS.pdfBug && StepperManager.enabled) { + stepper = StepperManager.create(this.pageNumber); stepper.init(IRQueue); stepper.nextBreakPoint = stepper.getNextBreakPoint(); } diff --git a/src/debugger.js b/src/debugger.js index 372ebd68f..3741eb0f0 100644 --- a/src/debugger.js +++ b/src/debugger.js @@ -138,7 +138,7 @@ var FontInspector = (function FontInspectorClosure() { })(); // Manages all the page steppers. -var Debugger = (function DeuggerClosure() { +var StepperManager = (function StepperManagerClosure() { var steppers = []; var stepperDiv = null; var stepperControls = null; @@ -146,8 +146,8 @@ var Debugger = (function DeuggerClosure() { var breakPoints = {}; return { // Poperties/functions needed by PDFBug. - id: 'Debugger', - name: 'Debugger', + id: 'Stepper', + name: 'Stepper', panel: null, manager: null, init: function init() { @@ -167,7 +167,7 @@ var Debugger = (function DeuggerClosure() { }, enabled: false, active: false, - // Debugger specific functions. + // Stepper specific functions. create: function create(pageNumber) { var debug = document.createElement('div'); debug.id = 'stepper' + pageNumber; @@ -179,12 +179,11 @@ var Debugger = (function DeuggerClosure() { b.value = pageNumber; stepperChooser.appendChild(b); var initBreakPoints = breakPoints[pageNumber] || []; - var pdfDebuggerStepper = new DebuggerStepper(debug, pageNumber, - initBreakPoints); - steppers.push(pdfDebuggerStepper); + var stepper = new Stepper(debug, pageNumber, initBreakPoints); + steppers.push(stepper); if (steppers.length === 1) this.selectStepper(pageNumber, false); - return pdfDebuggerStepper; + return stepper; }, selectStepper: function selectStepper(pageNumber, selectPanel) { if (selectPanel) @@ -205,8 +204,8 @@ var Debugger = (function DeuggerClosure() { })(); // The stepper for each page's IRQueue. -var DebuggerStepper = (function DebuggerStepperClosure() { - function DebuggerStepper(panel, pageNumber, initialBreakPoints) { +var Stepper = (function StepperClosure() { + function Stepper(panel, pageNumber, initialBreakPoints) { this.panel = panel; this.len; this.breakPoint = 0; @@ -215,7 +214,7 @@ var DebuggerStepper = (function DebuggerStepperClosure() { this.breakPoints = initialBreakPoints; this.currentIdx = -1; } - DebuggerStepper.prototype = { + Stepper.prototype = { init: function init(IRQueue) { function c(tag, textContent) { var d = document.createElement(tag); @@ -256,7 +255,7 @@ var DebuggerStepper = (function DebuggerStepperClosure() { self.breakPoints.push(x); else self.breakPoints.splice(self.breakPoints.indexOf(x), 1); - Debugger.saveBreakPoints(self.pageNumber, self.breakPoints); + StepperManager.saveBreakPoints(self.pageNumber, self.breakPoints); } })(i); @@ -278,7 +277,7 @@ var DebuggerStepper = (function DebuggerStepperClosure() { return null; }, breakIt: function breakIt(idx, callback) { - Debugger.selectStepper(this.pageNumber, true); + StepperManager.selectStepper(this.pageNumber, true); var self = this; var dom = document; self.currentIdx = idx; @@ -314,7 +313,7 @@ var DebuggerStepper = (function DebuggerStepperClosure() { } } }; - return DebuggerStepper; + return Stepper; })(); // Manages all the debugging tools. @@ -326,12 +325,12 @@ var PDFBug = (function PDFBugClosure() { return { tools: [ FontInspector, - Debugger + StepperManager ], init: function init() { /* * Basic Layout: - * Debugger + * PDFBug * Controls * Panels * Panel @@ -339,7 +338,7 @@ var PDFBug = (function PDFBugClosure() { * ... */ var ui = document.createElement('div'); - ui.id = 'debugger'; + ui.id = 'PDFBug'; var controls = document.createElement('div'); controls.setAttribute('class', 'controls'); diff --git a/web/viewer.css b/web/viewer.css index 6e40282fe..84a79cc83 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -404,7 +404,7 @@ canvas { text-align: center; } -#debugger { +#PDFBug { font-size: 10px; position: fixed; top: 35px; @@ -415,12 +415,12 @@ canvas { border: 1px solid #666; padding: 0; } -#debugger .controls { +#PDFBug .controls { border-bottom: 1px solid #666; padding: 3px; background: -moz-linear-gradient(center bottom, #eee 0%, #fff 100%); } -#debugger .panels { +#PDFBug .panels { overflow: auto; position: absolute; top: 27px; @@ -428,7 +428,7 @@ canvas { right: 0; bottom: 0; } -#debugger button.active { +#PDFBug button.active { font-weight: bold; } .debuggerShowText { From 45e3db77f235bbae038ebb8f19738cc394b4d28d Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 15 Feb 2012 14:38:18 -0800 Subject: [PATCH 6/9] Fix the font inspector. --- src/debugger.js | 23 +++++++++-------------- web/viewer.js | 1 + 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/debugger.js b/src/debugger.js index 3741eb0f0..d647e7489 100644 --- a/src/debugger.js +++ b/src/debugger.js @@ -7,31 +7,26 @@ var FontInspector = (function FontInspectorClosure() { var fonts; var panelWidth = 300; var active = false; + var fontAttribute = 'data-font-name'; function removeSelection() { - var divs = document.getElementsByTagName('div'); + var divs = document.querySelectorAll('div[' + fontAttribute + ']'); for (var i = 0; i < divs.length; ++i) { - var div = divs[i], style = div.getAttribute('style'); - if (!style || style.indexOf('pdfFont') < 0) continue; - var m = /(pdfFont\d+)/.exec(style); - div.dataset.fontName = ''; + var div = divs[i]; div.className = ''; } } function resetSelection() { - var divs = document.getElementsByTagName('div'); + var divs = document.querySelectorAll('div[' + fontAttribute + ']'); for (var i = 0; i < divs.length; ++i) { - var div = divs[i], style = div.getAttribute('style'); - if (!style || style.indexOf('pdfFont') < 0) continue; - var m = /(pdfFont\d+)/.exec(style); - div.dataset.fontName = m[1]; + var div = divs[i]; div.className = 'debuggerHideText'; } } function selectFont(fontName, show) { - var divs = document.getElementsByTagName('div'); + var divs = document.querySelectorAll('div[' + fontAttribute + '=' + + fontName + ']'); for (var i = 0; i < divs.length; ++i) { - var div = divs[i], style = div.getAttribute('style'); - if (div.dataset.fontName != fontName) continue; + var div = divs[i]; div.className = show ? 'debuggerShowText' : 'debuggerHideText'; } } @@ -75,7 +70,7 @@ var FontInspector = (function FontInspectorClosure() { document.body.addEventListener('click', textLayerClick, true); resetSelection(); } else { - document.body.removeEventListener('click', textLayerClick); + document.body.removeEventListener('click', textLayerClick, true); removeSelection(); } }, diff --git a/web/viewer.js b/web/viewer.js index 5381f69c1..602979e2e 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1085,6 +1085,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { // vScale and hScale already contain the scaling to pixel units var fontHeight = fontSize * text.geom.vScale; textDiv.dataset.canvasWidth = text.canvasWidth * text.geom.hScale; + textDiv.dataset.fontName = fontName; textDiv.style.fontSize = fontHeight + 'px'; textDiv.style.left = text.geom.x + 'px'; From f17a1679eb706db71ce60808742ebc46d0d52f46 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 15 Feb 2012 14:55:16 -0800 Subject: [PATCH 7/9] Move debugger to the web folder. --- Makefile | 2 +- src/core.js | 1 + src/worker_loader.js | 3 +-- {src => web}/debugger.js | 0 web/viewer.html | 3 ++- 5 files changed, 5 insertions(+), 4 deletions(-) rename {src => web}/debugger.js (100%) diff --git a/Makefile b/Makefile index e13c6bf3e..7688025a5 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,6 @@ PDF_JS_FILES = \ pattern.js \ stream.js \ worker.js \ - debugger.js \ ../external/jpgjs/jpg.js \ jpx.js \ $(NULL) @@ -216,6 +215,7 @@ EXTENSION_WEB_FILES = \ web/viewer.js \ web/viewer.html \ web/viewer-production.html \ + web/debugger.js \ $(NULL) FIREFOX_BUILD_DIR := $(BUILD_DIR)/firefox diff --git a/src/core.js b/src/core.js index 3482f225b..358dc8ffb 100644 --- a/src/core.js +++ b/src/core.js @@ -57,6 +57,7 @@ function getPdf(arg, callback) { xhr.send(null); } globalScope.PDFJS.getPdf = getPdf; +globalScope.PDFJS.pdfBug = false; var Page = (function PageClosure() { function Page(xref, pageNumber, pageDict, ref) { diff --git a/src/worker_loader.js b/src/worker_loader.js index c3edc9928..fc3d7a5f7 100644 --- a/src/worker_loader.js +++ b/src/worker_loader.js @@ -24,8 +24,7 @@ var files = [ 'stream.js', 'worker.js', '../external/jpgjs/jpg.js', - 'jpx.js', - 'debugger.js' + 'jpx.js' ]; // Load all the files. diff --git a/src/debugger.js b/web/debugger.js similarity index 100% rename from src/debugger.js rename to web/debugger.js diff --git a/web/viewer.html b/web/viewer.html index 92a0edc40..ee992a2c5 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -29,10 +29,11 @@ - + + From 5e04ad5e3a40803e0c051533d9d51231a046d867 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 15 Feb 2012 16:03:04 -0800 Subject: [PATCH 8/9] Move special debug flags to the hash section of the url. --- web/viewer.js | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index 602979e2e..41b9fcfc6 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -509,13 +509,7 @@ var PDFView = { return; if (hash.indexOf('=') >= 0) { - // parsing query string - var paramsPairs = hash.split('&'); - var params = {}; - for (var i = 0; i < paramsPairs.length; ++i) { - var paramPair = paramsPairs[i].split('='); - params[paramPair[0]] = paramPair[1]; - } + var params = PDFView.parseQueryString(hash); // borrowing syntax from "Parameters for Opening PDF Files" if ('nameddest' in params) { PDFView.navigateTo(params.nameddest); @@ -627,6 +621,16 @@ var PDFView = { } return visibleThumbs; + }, + + // Helper function to parse query string (e.g. ?param1=value&parm2=...). + parseQueryString: function pdfViewParseQueryString(query) { + var params = query.split('&'); + for (var i = 0; i < params.length; i++) { + var param = params[i].split('='); + params[unescape(param[0])] = unescape(param[1]); + } + return params; } }; @@ -1097,16 +1101,11 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { }; window.addEventListener('load', function webViewerLoad(evt) { - var params = document.location.search.substring(1).split('&'); - for (var i = 0; i < params.length; i++) { - var param = params[i].split('='); - params[unescape(param[0])] = unescape(param[1]); - } + var params = PDFView.parseQueryString(document.location.search.substring(1)); - var scale = ('scale' in params) ? params.scale : 0; var file = PDFJS.isFirefoxExtension ? window.location.toString() : params.file || kDefaultURL; - PDFView.open(file, parseFloat(scale)); + PDFView.open(file, 0); if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader || !window.FileList || !window.Blob) { @@ -1117,15 +1116,19 @@ window.addEventListener('load', function webViewerLoad(evt) { document.getElementById('fileInput').value = null; } - if ('disableWorker' in params) - PDFJS.disableWorker = (params['disableWorker'] === 'true'); + // Special debugging flags in the hash section of the URL. + var hash = document.location.hash.substring(1); + var hashParams = PDFView.parseQueryString(hash); - if ('disableTextLayer' in params) - PDFJS.disableTextLayer = (params['disableTextLayer'] === 'true'); + if ('disableWorker' in hashParams) + PDFJS.disableWorker = (hashParams['disableWorker'] === 'true'); - if ('pdfBug' in params) { + if ('disableTextLayer' in hashParams) + PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true'); + + if ('pdfBug' in hashParams) { PDFJS.pdfBug = true; - var pdfBug = params['pdfBug']; + var pdfBug = hashParams['pdfBug']; var all = false, enabled = []; if (pdfBug === 'all') all = true; From 0f4730c8259519ab59f02c74d3445547382ce8ca Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 16 Feb 2012 09:55:09 -0800 Subject: [PATCH 9/9] Address review comments. --- web/debugger.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/web/debugger.js b/web/debugger.js index d647e7489..c759a5ee8 100644 --- a/web/debugger.js +++ b/web/debugger.js @@ -10,14 +10,14 @@ var FontInspector = (function FontInspectorClosure() { var fontAttribute = 'data-font-name'; function removeSelection() { var divs = document.querySelectorAll('div[' + fontAttribute + ']'); - for (var i = 0; i < divs.length; ++i) { + for (var i = 0, ii = divs.length; i < ii; ++i) { var div = divs[i]; div.className = ''; } } function resetSelection() { var divs = document.querySelectorAll('div[' + fontAttribute + ']'); - for (var i = 0; i < divs.length; ++i) { + for (var i = 0, ii = divs.length; i < ii; ++i) { var div = divs[i]; div.className = 'debuggerHideText'; } @@ -25,7 +25,7 @@ var FontInspector = (function FontInspectorClosure() { function selectFont(fontName, show) { var divs = document.querySelectorAll('div[' + fontAttribute + '=' + fontName + ']'); - for (var i = 0; i < divs.length; ++i) { + for (var i = 0, ii = divs.length; i < ii; ++i) { var div = divs[i]; div.className = show ? 'debuggerShowText' : 'debuggerHideText'; } @@ -211,6 +211,7 @@ var Stepper = (function StepperClosure() { } Stepper.prototype = { init: function init(IRQueue) { + // Shorter way to create element and optionally set textContent. function c(tag, textContent) { var d = document.createElement(tag); if (textContent) @@ -219,7 +220,7 @@ var Stepper = (function StepperClosure() { } var panel = this.panel; this.len = IRQueue.fnArray.length; - var content = c('div', 'c=contine, s=step'); + var content = c('div', 'c=continue, s=step'); var table = c('table'); content.appendChild(table); table.cellSpacing = 0;