Improved annotations' display/behavior.
Added an "InteractiveAnnotation" class to homogenize the annotations' structure (highlighting) and user interactions (for now, used for text and link annotations). Text annotations: The appearance (AP) has priority over the icon (Name). The popup extends horizontally (up to a limit) as well as vertically. Reduced the title's font size. The annotation's color (C) is used to color the popup's background. On top of the mouseover show/hide behavior, a click on the icon will lock the annotation open (for mobile purposes). It can be closed with another click on either the icon or the popup. An annotation printing is conditioned by its "print" bit Unsupported annotations are not displayed at all.
This commit is contained in:
parent
3e931048f2
commit
076b3433b4
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
var showAnnotation = function showAnnotation(pin) {
|
||||||
|
if (pin) {
|
||||||
|
pinned = true;
|
||||||
|
}
|
||||||
|
if (content.hasAttribute('hidden')) {
|
||||||
container.style.zIndex += 1;
|
container.style.zIndex += 1;
|
||||||
content.removeAttribute('hidden');
|
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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
7
web/images/annotation-noicon.svg
Normal file
7
web/images/annotation-noicon.svg
Normal 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 |
@ -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) {
|
||||||
|
var link = element.getElementsByTagName('a')[0];
|
||||||
|
if (link) {
|
||||||
if (data.action) {
|
if (data.action) {
|
||||||
bindNamedAction(element, data.action);
|
bindNamedAction(link, data.action);
|
||||||
} else {
|
} else {
|
||||||
bindLink(element, ('dest' in data) ? data.dest : null);
|
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();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user