Merge pull request #4318 from dferer/improveAnnotationsDisplay

Improved annotations' display/behavior.
This commit is contained in:
Yury Delendik 2014-03-07 09:42:42 -06:00
commit 01b23439a9
8 changed files with 305 additions and 131 deletions

View File

@ -134,7 +134,7 @@ var Page = (function PageClosure() {
}.bind(this)); }.bind(this));
return promise; return promise;
}, },
getOperatorList: function Page_getOperatorList(handler) { getOperatorList: function Page_getOperatorList(handler, intent) {
var self = this; var self = this;
var promise = new LegacyPromise(); var promise = new LegacyPromise();
@ -169,11 +169,12 @@ var Page = (function PageClosure() {
var contentStream = data[0]; var contentStream = data[0];
var opList = new OperatorList(handler, self.pageIndex); var opList = new OperatorList(intent, handler, self.pageIndex);
handler.send('StartRenderPage', { handler.send('StartRenderPage', {
transparency: partialEvaluator.hasBlendModes(self.resources), transparency: partialEvaluator.hasBlendModes(self.resources),
pageIndex: self.pageIndex pageIndex: self.pageIndex,
intent: intent
}); });
partialEvaluator.getOperatorList(contentStream, self.resources, opList); partialEvaluator.getOperatorList(contentStream, self.resources, opList);
pageListPromise.resolve(opList); pageListPromise.resolve(opList);
@ -191,7 +192,7 @@ var Page = (function PageClosure() {
} }
var annotationsReadyPromise = Annotation.appendToOperatorList( var annotationsReadyPromise = Annotation.appendToOperatorList(
annotations, pageOpList, pdfManager, partialEvaluator); annotations, pageOpList, pdfManager, partialEvaluator, intent);
annotationsReadyPromise.then(function () { annotationsReadyPromise.then(function () {
pageOpList.flush(true); pageOpList.flush(true);
promise.resolve(pageOpList); promise.resolve(pageOpList);

View File

@ -1376,7 +1376,7 @@ var OperatorList = (function OperatorListClosure() {
} }
function OperatorList(messageHandler, pageIndex) { function OperatorList(intent, messageHandler, pageIndex) {
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
// When there isn't a message handler the fn array needs to be able to grow // When there isn't a message handler the fn array needs to be able to grow
// since we can't flush the operators. // since we can't flush the operators.
@ -1389,6 +1389,7 @@ var OperatorList = (function OperatorListClosure() {
this.dependencies = {}; this.dependencies = {};
this.pageIndex = pageIndex; this.pageIndex = pageIndex;
this.fnIndex = 0; this.fnIndex = 0;
this.intent = intent;
} }
OperatorList.prototype = { OperatorList.prototype = {
@ -1449,7 +1450,8 @@ var OperatorList = (function OperatorListClosure() {
lastChunk: lastChunk, lastChunk: lastChunk,
length: this.length length: this.length
}, },
pageIndex: this.pageIndex pageIndex: this.pageIndex,
intent: this.intent
}, null, transfers); }, null, transfers);
this.dependencies = []; this.dependencies = [];
this.fnIndex = 0; this.fnIndex = 0;

View File

@ -334,7 +334,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
var pageNum = data.pageIndex + 1; var pageNum = data.pageIndex + 1;
var start = Date.now(); var start = Date.now();
// Pre compile the pdf page and fetch the fonts/images. // Pre compile the pdf page and fetch the fonts/images.
page.getOperatorList(handler).then(function(operatorList) { page.getOperatorList(handler, data.intent).then(function(operatorList) {
info('page=' + pageNum + ' - getOperatorList: time=' + info('page=' + pageNum + ' - getOperatorList: time=' +
(Date.now() - start) + 'ms, len=' + operatorList.fnArray.length); (Date.now() - start) + 'ms, len=' + operatorList.fnArray.length);
@ -366,7 +366,8 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
handler.send('PageError', { handler.send('PageError', {
pageNum: pageNum, pageNum: pageNum,
error: wrappedException error: wrappedException,
intent: data.intent
}); });
}); });
}); });

View File

@ -341,10 +341,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
this.stats.enabled = !!globalScope.PDFJS.enableStats; this.stats.enabled = !!globalScope.PDFJS.enableStats;
this.commonObjs = transport.commonObjs; this.commonObjs = transport.commonObjs;
this.objs = new PDFObjects(); this.objs = new PDFObjects();
this.receivingOperatorList = false;
this.cleanupAfterRender = false; this.cleanupAfterRender = false;
this.pendingDestroy = false; this.pendingDestroy = false;
this.renderTasks = []; this.intentStates = {};
} }
PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ { PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ {
/** /**
@ -423,12 +422,21 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
// this call to render. // this call to render.
this.pendingDestroy = false; this.pendingDestroy = false;
var renderingIntent = 'intent' in params ?
(params.intent == 'print' ? 'print' : 'display') :
'display';
if (!this.intentStates[renderingIntent]) {
this.intentStates[renderingIntent] = {};
}
var intentState = this.intentStates[renderingIntent];
// If there is no displayReadyPromise yet, then the operatorList was never // If there is no displayReadyPromise yet, then the operatorList was never
// requested before. Make the request and create the promise. // requested before. Make the request and create the promise.
if (!this.displayReadyPromise) { if (!intentState.displayReadyPromise) {
this.receivingOperatorList = true; intentState.receivingOperatorList = true;
this.displayReadyPromise = new LegacyPromise(); intentState.displayReadyPromise = new LegacyPromise();
this.operatorList = { intentState.operatorList = {
fnArray: [], fnArray: [],
argsArray: [], argsArray: [],
lastChunk: false lastChunk: false
@ -436,18 +444,23 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
this.stats.time('Page Request'); this.stats.time('Page Request');
this.transport.messageHandler.send('RenderPageRequest', { this.transport.messageHandler.send('RenderPageRequest', {
pageIndex: this.pageNumber - 1 pageIndex: this.pageNumber - 1,
intent: renderingIntent
}); });
} }
var internalRenderTask = new InternalRenderTask(complete, params, var internalRenderTask = new InternalRenderTask(complete, params,
this.objs, this.commonObjs, this.objs, this.commonObjs,
this.operatorList, this.pageNumber); intentState.operatorList,
this.renderTasks.push(internalRenderTask); this.pageNumber);
if (!intentState.renderTasks) {
intentState.renderTasks = [];
}
intentState.renderTasks.push(internalRenderTask);
var renderTask = new RenderTask(internalRenderTask); var renderTask = new RenderTask(internalRenderTask);
var self = this; var self = this;
this.displayReadyPromise.then( intentState.displayReadyPromise.then(
function pageDisplayReadyPromise(transparency) { function pageDisplayReadyPromise(transparency) {
if (self.pendingDestroy) { if (self.pendingDestroy) {
complete(); complete();
@ -463,9 +476,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
); );
function complete(error) { function complete(error) {
var i = self.renderTasks.indexOf(internalRenderTask); var i = intentState.renderTasks.indexOf(internalRenderTask);
if (i >= 0) { if (i >= 0) {
self.renderTasks.splice(i, 1); intentState.renderTasks.splice(i, 1);
} }
if (self.cleanupAfterRender) { if (self.cleanupAfterRender) {
@ -513,14 +526,17 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
*/ */
_tryDestroy: function PDFPageProxy__destroy() { _tryDestroy: function PDFPageProxy__destroy() {
if (!this.pendingDestroy || if (!this.pendingDestroy ||
this.renderTasks.length !== 0 || Object.keys(this.intentStates).some(function(intent) {
this.receivingOperatorList) { var intentState = this.intentStates[intent];
return intentState.renderTasks.length !== 0 ||
intentState.receivingOperatorList;
}, this)) {
return; return;
} }
delete this.operatorList; Object.keys(this.intentStates).forEach(function(intent) {
delete this.displayReadyPromise; delete this.intentStates[intent];
delete this.annotationsPromise; }, this);
this.objs.clear(); this.objs.clear();
this.pendingDestroy = false; this.pendingDestroy = false;
}, },
@ -528,28 +544,33 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
* For internal use only. * For internal use only.
* @ignore * @ignore
*/ */
_startRenderPage: function PDFPageProxy_startRenderPage(transparency) { _startRenderPage: function PDFPageProxy_startRenderPage(transparency,
this.displayReadyPromise.resolve(transparency); intent) {
var intentState = this.intentStates[intent];
intentState.displayReadyPromise.resolve(transparency);
}, },
/** /**
* For internal use only. * For internal use only.
* @ignore * @ignore
*/ */
_renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk) { _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk,
intent) {
var intentState = this.intentStates[intent];
// Add the new chunk to the current operator list. // Add the new chunk to the current operator list.
for (var i = 0, ii = operatorListChunk.length; i < ii; i++) { for (var i = 0, ii = operatorListChunk.length; i < ii; i++) {
this.operatorList.fnArray.push(operatorListChunk.fnArray[i]); intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
this.operatorList.argsArray.push(operatorListChunk.argsArray[i]); intentState.operatorList.argsArray.push(
operatorListChunk.argsArray[i]);
} }
this.operatorList.lastChunk = operatorListChunk.lastChunk; intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
// Notify all the rendering tasks there are more operators to be consumed. // Notify all the rendering tasks there are more operators to be consumed.
for (var i = 0; i < this.renderTasks.length; i++) { for (var i = 0; i < intentState.renderTasks.length; i++) {
this.renderTasks[i].operatorListChanged(); intentState.renderTasks[i].operatorListChanged();
} }
if (operatorListChunk.lastChunk) { if (operatorListChunk.lastChunk) {
this.receivingOperatorList = false; intentState.receivingOperatorList = false;
this._tryDestroy(); this._tryDestroy();
} }
} }
@ -775,13 +796,13 @@ var WorkerTransport = (function WorkerTransportClosure() {
var page = this.pageCache[data.pageIndex]; var page = this.pageCache[data.pageIndex];
page.stats.timeEnd('Page Request'); page.stats.timeEnd('Page Request');
page._startRenderPage(data.transparency); page._startRenderPage(data.transparency, data.intent);
}, this); }, this);
messageHandler.on('RenderPageChunk', function transportRender(data) { messageHandler.on('RenderPageChunk', function transportRender(data) {
var page = this.pageCache[data.pageIndex]; var page = this.pageCache[data.pageIndex];
page._renderPageChunk(data.operatorList); page._renderPageChunk(data.operatorList, data.intent);
}, this); }, this);
messageHandler.on('commonobj', function transportObj(data) { messageHandler.on('commonobj', function transportObj(data) {
@ -824,8 +845,9 @@ var WorkerTransport = (function WorkerTransportClosure() {
var pageIndex = data[1]; var pageIndex = data[1];
var type = data[2]; var type = data[2];
var pageProxy = this.pageCache[pageIndex]; var pageProxy = this.pageCache[pageIndex];
if (pageProxy.objs.hasData(id)) if (pageProxy.objs.hasData(id)) {
return; return;
}
switch (type) { switch (type) {
case 'JpegStream': case 'JpegStream':
@ -861,10 +883,11 @@ var WorkerTransport = (function WorkerTransportClosure() {
this.workerReadyPromise.reject(data); this.workerReadyPromise.reject(data);
}, this); }, this);
messageHandler.on('PageError', function transportError(data) { messageHandler.on('PageError', function transportError(data, intent) {
var page = this.pageCache[data.pageNum - 1]; var page = this.pageCache[data.pageNum - 1];
if (page.displayReadyPromise) var intentState = page.intentStates[intent];
page.displayReadyPromise.reject(data.error); if (intentState.displayReadyPromise)
intentState.displayReadyPromise.reject(data.error);
else else
error(data.error); error(data.error);
}, this); }, this);

View File

@ -21,6 +21,9 @@
'use strict'; 'use strict';
var HIGHLIGHT_OFFSET = 4; // px
var SUPPORTED_TYPES = ['Link', 'Text', 'Widget'];
var Annotation = (function AnnotationClosure() { var Annotation = (function AnnotationClosure() {
// 12.5.5: Algorithm: Appearance streams // 12.5.5: Algorithm: Appearance streams
function getTransformMatrix(rect, bbox, matrix) { function getTransformMatrix(rect, bbox, matrix) {
@ -143,25 +146,50 @@ var Annotation = (function AnnotationClosure() {
}, },
// TODO(mack): Remove this, it's not really that helpful. // TODO(mack): Remove this, it's not really that helpful.
getEmptyContainer: function Annotation_getEmptyContainer(tagName, rect) { getEmptyContainer: function Annotation_getEmptyContainer(tagName, rect,
borderWidth) {
assert(!isWorker, assert(!isWorker,
'getEmptyContainer() should be called from main thread'); 'getEmptyContainer() should be called from main thread');
var bWidth = borderWidth || 0;
rect = rect || this.data.rect; rect = rect || this.data.rect;
var element = document.createElement(tagName); var element = document.createElement(tagName);
element.style.width = Math.ceil(rect[2] - rect[0]) + 'px'; element.style.borderWidth = bWidth + 'px';
element.style.height = Math.ceil(rect[3] - rect[1]) + 'px'; var width = rect[2] - rect[0] - 2 * bWidth;
var height = rect[3] - rect[1] - 2 * bWidth;
element.style.width = width + 'px';
element.style.height = height + 'px';
return element; return element;
}, },
isInvisible: function Annotation_isInvisible() {
var data = this.data;
if (data && SUPPORTED_TYPES.indexOf(data.subtype) !== -1) {
return false;
} else {
return !!(data &&
data.annotationFlags && // Default: not invisible
data.annotationFlags & 0x1); // Invisible
}
},
isViewable: function Annotation_isViewable() { isViewable: function Annotation_isViewable() {
var data = this.data; var data = this.data;
return !!( return !!(!this.isInvisible() &&
data && data &&
(!data.annotationFlags || (!data.annotationFlags ||
!(data.annotationFlags & 0x22)) && // Hidden or NoView !(data.annotationFlags & 0x22)) && // Hidden or NoView
data.rect // rectangle is nessessary data.rect); // rectangle is nessessary
); },
isPrintable: function Annotation_isPrintable() {
var data = this.data;
return !!(!this.isInvisible() &&
data &&
data.annotationFlags && // Default: not printable
data.annotationFlags & 0x4 && // Print
data.rect); // rectangle is nessessary
}, },
loadResources: function(keys) { loadResources: function(keys) {
@ -182,7 +210,7 @@ var Annotation = (function AnnotationClosure() {
return promise; return promise;
}, },
getOperatorList: function Annotation_getToOperatorList(evaluator) { getOperatorList: function Annotation_getOperatorList(evaluator) {
var promise = new LegacyPromise(); var promise = new LegacyPromise();
@ -289,7 +317,7 @@ var Annotation = (function AnnotationClosure() {
var annotation = new Constructor(params); var annotation = new Constructor(params);
if (annotation.isViewable()) { if (annotation.isViewable() || annotation.isPrintable()) {
return annotation; return annotation;
} else { } else {
warn('unimplemented annotation type: ' + subtype); warn('unimplemented annotation type: ' + subtype);
@ -297,7 +325,7 @@ var Annotation = (function AnnotationClosure() {
}; };
Annotation.appendToOperatorList = function Annotation_appendToOperatorList( Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
annotations, opList, pdfManager, partialEvaluator) { annotations, opList, pdfManager, partialEvaluator, intent) {
function reject(e) { function reject(e) {
annotationsReadyPromise.reject(e); annotationsReadyPromise.reject(e);
@ -307,7 +335,11 @@ var Annotation = (function AnnotationClosure() {
var annotationPromises = []; var annotationPromises = [];
for (var i = 0, n = annotations.length; i < n; ++i) { for (var i = 0, n = annotations.length; i < n; ++i) {
annotationPromises.push(annotations[i].getOperatorList(partialEvaluator)); if (intent === 'display' && annotations[i].isViewable() ||
intent === 'print' && annotations[i].isPrintable()) {
annotationPromises.push(
annotations[i].getOperatorList(partialEvaluator));
}
} }
Promise.all(annotationPromises).then(function(datas) { Promise.all(annotationPromises).then(function(datas) {
opList.addOp(OPS.beginAnnotations, []); opList.addOp(OPS.beginAnnotations, []);
@ -519,9 +551,64 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
return TextWidgetAnnotation; return TextWidgetAnnotation;
})(); })();
var InteractiveAnnotation = (function InteractiveAnnotationClosure() {
function InteractiveAnnotation(params) {
Annotation.call(this, params);
}
Util.inherit(InteractiveAnnotation, Annotation, {
hasHtml: function InteractiveAnnotation_hasHtml() {
return true;
},
highlight: function InteractiveAnnotation_highlight() {
if (this.highlightElement &&
this.highlightElement.hasAttribute('hidden')) {
this.highlightElement.removeAttribute('hidden');
}
},
unhighlight: function InteractiveAnnotation_unhighlight() {
if (this.highlightElement &&
!this.highlightElement.hasAttribute('hidden')) {
this.highlightElement.setAttribute('hidden', true);
}
},
initContainer: function InteractiveAnnotation_initContainer() {
var item = this.data;
var rect = item.rect;
var container = this.getEmptyContainer('section', rect, item.borderWidth);
container.style.backgroundColor = item.color;
var color = item.color;
var rgb = [];
for (var i = 0; i < 3; ++i) {
rgb[i] = Math.round(color[i] * 255);
}
item.colorCssRgb = Util.makeCssRgb(rgb);
var highlight = document.createElement('div');
highlight.className = 'annotationHighlight';
highlight.style.left = highlight.style.top = -HIGHLIGHT_OFFSET + 'px';
highlight.style.right = highlight.style.bottom = -HIGHLIGHT_OFFSET + 'px';
highlight.setAttribute('hidden', true);
this.highlightElement = highlight;
container.appendChild(this.highlightElement);
return container;
}
});
return InteractiveAnnotation;
})();
var TextAnnotation = (function TextAnnotationClosure() { var TextAnnotation = (function TextAnnotationClosure() {
function TextAnnotation(params) { function TextAnnotation(params) {
Annotation.call(this, params); InteractiveAnnotation.call(this, params);
if (params.data) { if (params.data) {
return; return;
@ -534,22 +621,21 @@ var TextAnnotation = (function TextAnnotationClosure() {
var title = dict.get('T'); var title = dict.get('T');
data.content = stringToPDFString(content || ''); data.content = stringToPDFString(content || '');
data.title = stringToPDFString(title || ''); data.title = stringToPDFString(title || '');
data.name = !dict.has('Name') ? 'Note' : dict.get('Name').name;
if (data.hasAppearance) {
data.name = 'NoIcon';
} else {
data.name = dict.has('Name') ? dict.get('Name').name : 'Note';
}
if (dict.has('C')) {
data.hasBgColor = true;
}
} }
var ANNOT_MIN_SIZE = 10; var ANNOT_MIN_SIZE = 10;
Util.inherit(TextAnnotation, Annotation, { Util.inherit(TextAnnotation, InteractiveAnnotation, {
getOperatorList: function TextAnnotation_getOperatorList(evaluator) {
var promise = new LegacyPromise();
promise.resolve(new OperatorList());
return promise;
},
hasHtml: function TextAnnotation_hasHtml() {
return true;
},
getHtmlElement: function TextAnnotation_getHtmlElement(commonObjs) { getHtmlElement: function TextAnnotation_getHtmlElement(commonObjs) {
assert(!isWorker, 'getHtmlElement() shall be called from main thread'); assert(!isWorker, 'getHtmlElement() shall be called from main thread');
@ -565,23 +651,40 @@ var TextAnnotation = (function TextAnnotationClosure() {
rect[2] = rect[0] + (rect[3] - rect[1]); // make it square rect[2] = rect[0] + (rect[3] - rect[1]); // make it square
} }
var container = this.getEmptyContainer('section', rect); var container = this.initContainer();
container.className = 'annotText'; container.className = 'annotText';
var image = document.createElement('img'); var image = document.createElement('img');
image.style.height = container.style.height; image.style.height = container.style.height;
image.style.width = container.style.width;
var iconName = item.name; var iconName = item.name;
image.src = PDFJS.imageResourcesPath + 'annotation-' + image.src = PDFJS.imageResourcesPath + 'annotation-' +
iconName.toLowerCase() + '.svg'; iconName.toLowerCase() + '.svg';
image.alt = '[{{type}} Annotation]'; image.alt = '[{{type}} Annotation]';
image.dataset.l10nId = 'text_annotation_type'; image.dataset.l10nId = 'text_annotation_type';
image.dataset.l10nArgs = JSON.stringify({type: iconName}); image.dataset.l10nArgs = JSON.stringify({type: iconName});
var contentWrapper = document.createElement('div');
contentWrapper.className = 'annotTextContentWrapper';
contentWrapper.style.left = Math.floor(rect[2] - rect[0] + 5) + 'px';
contentWrapper.style.top = '-10px';
var content = document.createElement('div'); var content = document.createElement('div');
content.className = 'annotTextContent';
content.setAttribute('hidden', true); content.setAttribute('hidden', true);
if (item.hasBgColor) {
var color = item.color;
var rgb = [];
for (var i = 0; i < 3; ++i) {
// Enlighten the color (70%)
var c = Math.round(color[i] * 255);
rgb[i] = Math.round((255 - c) * 0.7) + c;
}
content.style.backgroundColor = Util.makeCssRgb(rgb);
}
var title = document.createElement('h1'); var title = document.createElement('h1');
var text = document.createElement('p'); var text = document.createElement('p');
content.style.left = Math.floor(rect[2] - rect[0]) + 'px';
content.style.top = '0px';
title.textContent = item.title; title.textContent = item.title;
if (!item.content && !item.title) { if (!item.content && !item.title) {
@ -597,28 +700,57 @@ var TextAnnotation = (function TextAnnotationClosure() {
} }
text.appendChild(e); text.appendChild(e);
var showAnnotation = function showAnnotation() { var pinned = false;
container.style.zIndex += 1;
content.removeAttribute('hidden'); var showAnnotation = function showAnnotation(pin) {
if (pin) {
pinned = true;
}
if (content.hasAttribute('hidden')) {
container.style.zIndex += 1;
content.removeAttribute('hidden');
}
}; };
var hideAnnotation = function hideAnnotation(e) { var hideAnnotation = function hideAnnotation(unpin) {
if (e.toElement || e.relatedTarget) { // No context menu is used if (unpin) {
pinned = false;
}
if (!content.hasAttribute('hidden') && !pinned) {
container.style.zIndex -= 1; container.style.zIndex -= 1;
content.setAttribute('hidden', true); content.setAttribute('hidden', true);
} }
}; };
content.addEventListener('mouseover', showAnnotation, false); var toggleAnnotation = function toggleAnnotation() {
content.addEventListener('mouseout', hideAnnotation, false); if (pinned) {
image.addEventListener('mouseover', showAnnotation, false); hideAnnotation(true);
image.addEventListener('mouseout', hideAnnotation, false); } else {
showAnnotation(true);
}
};
var self = this;
image.addEventListener('click', function image_clickHandler() {
toggleAnnotation();
}, false);
image.addEventListener('mouseover', function image_mouseOverHandler() {
showAnnotation();
}, false);
image.addEventListener('mouseout', function image_mouseOutHandler() {
hideAnnotation();
}, false);
content.addEventListener('click', function content_clickHandler() {
hideAnnotation(true);
}, false);
} }
content.appendChild(title); content.appendChild(title);
content.appendChild(text); content.appendChild(text);
contentWrapper.appendChild(content);
container.appendChild(image); container.appendChild(image);
container.appendChild(content); container.appendChild(contentWrapper);
return container; return container;
} }
@ -629,7 +761,7 @@ var TextAnnotation = (function TextAnnotationClosure() {
var LinkAnnotation = (function LinkAnnotationClosure() { var LinkAnnotation = (function LinkAnnotationClosure() {
function LinkAnnotation(params) { function LinkAnnotation(params) {
Annotation.call(this, params); InteractiveAnnotation.call(this, params);
if (params.data) { if (params.data) {
return; return;
@ -692,36 +824,28 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
return url; return url;
} }
Util.inherit(LinkAnnotation, Annotation, { Util.inherit(LinkAnnotation, InteractiveAnnotation, {
hasOperatorList: function LinkAnnotation_hasOperatorList() { hasOperatorList: function LinkAnnotation_hasOperatorList() {
return false; return false;
}, },
hasHtml: function LinkAnnotation_hasHtml() {
return true;
},
getHtmlElement: function LinkAnnotation_getHtmlElement(commonObjs) { getHtmlElement: function LinkAnnotation_getHtmlElement(commonObjs) {
var rect = this.data.rect;
var element = document.createElement('a');
var borderWidth = this.data.borderWidth;
element.style.borderWidth = borderWidth + 'px'; var container = this.initContainer();
var color = this.data.color; container.className = 'annotLink';
var rgb = [];
for (var i = 0; i < 3; ++i) {
rgb[i] = Math.round(color[i] * 255);
}
element.style.borderColor = Util.makeCssRgb(rgb);
element.style.borderStyle = 'solid';
var width = rect[2] - rect[0] - 2 * borderWidth; var item = this.data;
var height = rect[3] - rect[1] - 2 * borderWidth; var rect = item.rect;
element.style.width = width + 'px';
element.style.height = height + 'px';
element.href = this.data.url || ''; container.style.borderColor = item.colorCssRgb;
return element; container.style.borderStyle = 'solid';
var link = document.createElement('a');
link.href = link.title = this.data.url || '';
container.appendChild(link);
return container;
} }
}); });

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
width="40"
height="40"
viewBox="0 0 40 40">
</svg>

After

Width:  |  Height:  |  Size: 158 B

View File

@ -306,10 +306,13 @@ var PageView = function pageView(container, id, scale,
CustomStyle.setProp('transformOrigin', element, transformOriginStr); CustomStyle.setProp('transformOrigin', element, transformOriginStr);
if (data.subtype === 'Link' && !data.url) { if (data.subtype === 'Link' && !data.url) {
if (data.action) { var link = element.getElementsByTagName('a')[0];
bindNamedAction(element, data.action); if (link) {
} else { if (data.action) {
bindLink(element, ('dest' in data) ? data.dest : null); bindNamedAction(link, data.action);
} else {
bindLink(link, ('dest' in data) ? data.dest : null);
}
} }
} }
@ -579,6 +582,7 @@ var PageView = function pageView(container, id, scale,
canvasContext: ctx, canvasContext: ctx,
viewport: this.viewport, viewport: this.viewport,
textLayer: textLayer, textLayer: textLayer,
// intent: 'default', // === 'display'
continueCallback: function pdfViewcContinueCallback(cont) { continueCallback: function pdfViewcContinueCallback(cont) {
if (PDFView.highestPriorityPage !== 'page' + self.id) { if (PDFView.highestPriorityPage !== 'page' + self.id) {
self.renderingState = RenderingStates.PAUSED; self.renderingState = RenderingStates.PAUSED;
@ -650,13 +654,13 @@ var PageView = function pageView(container, id, scale,
var renderContext = { var renderContext = {
canvasContext: ctx, canvasContext: ctx,
viewport: viewport viewport: viewport,
intent: 'print'
}; };
pdfPage.render(renderContext).promise.then(function() { pdfPage.render(renderContext).promise.then(function() {
// Tell the printEngine that rendering this canvas/page has finished. // Tell the printEngine that rendering this canvas/page has finished.
obj.done(); obj.done();
self.pdfPage.destroy();
}, function(error) { }, function(error) {
console.error(error); console.error(error);
// Tell the printEngine that rendering this canvas/page has failed. // Tell the printEngine that rendering this canvas/page has failed.
@ -666,7 +670,6 @@ var PageView = function pageView(container, id, scale,
} else { } else {
obj.done(); obj.done();
} }
self.pdfPage.destroy();
}); });
}; };
}; };

View File

@ -1247,14 +1247,7 @@ canvas {
background-color: white; background-color: white;
} }
.page > a, .annotLink > a:hover {
.annotationLayer > a {
display: block;
position: absolute;
}
.page > a:hover,
.annotationLayer > a:hover {
opacity: 0.2; opacity: 0.2;
background: #ff0; background: #ff0;
box-shadow: 0px 2px 10px #ff0; box-shadow: 0px 2px 10px #ff0;
@ -1319,29 +1312,49 @@ canvas {
::selection { background:rgba(0,0,255,0.3); } ::selection { background:rgba(0,0,255,0.3); }
::-moz-selection { background:rgba(0,0,255,0.3); } ::-moz-selection { background:rgba(0,0,255,0.3); }
.annotText > div { .annotationHighlight {
z-index: 200;
position: absolute; position: absolute;
padding: 0.6em; border: 2px #FFFF99 solid;
max-width: 20em;
background-color: #FFFF99;
box-shadow: 0px 2px 10px #333;
border-radius: 7px;
} }
.annotText > img { .annotText > img {
position: absolute; position: absolute;
opacity: 0.6; cursor: pointer;
} }
.annotText > img:hover { .annotTextContentWrapper {
opacity: 1; position: absolute;
width: 20em;
} }
.annotText > div > h1 { .annotTextContent {
font-size: 1.2em; z-index: 200;
float: left;
max-width: 20em;
background-color: #FFFF99;
box-shadow: 0px 2px 5px #333;
border-radius: 2px;
padding: 0.6em;
cursor: pointer;
}
.annotTextContent > h1 {
font-size: 1em;
border-bottom: 1px solid #000000; border-bottom: 1px solid #000000;
margin: 0px; padding-bottom: 0.2em;
}
.annotTextContent > p {
padding-top: 0.2em;
}
.annotLink > a {
position: absolute;
font-size: 1em;
top: 0;
left: 0;
width: 100%;
height: 100%;
} }
#errorWrapper { #errorWrapper {