this.page = page;
}
PdfPageWrapper.prototype = {
- get width() {
- return this.page.width;
- },
- get height() {
- return this.page.height;
+ get rotate() {
+ return this.page.rotate;
},
get stats() {
return this.page.stats;
get view() {
return this.page.view;
},
- rotatePoint: function(x, y) {
- return this.page.rotatePoint(x, y);
+ getViewport: function(scale, rotate) {
+ if (arguments < 2)
+ rotate = this.rotate;
+ return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
},
getAnnotations: function() {
var promise = new PDFJS.Promise();
render: function(renderContext) {
var promise = new PDFJS.Promise();
this.page.startRendering(renderContext.canvasContext,
+ renderContext.viewport,
function complete(error) {
if (error)
promise.reject(error);
'shadingFill': true
},
- beginDrawing: function CanvasGraphics_beginDrawing(mediaBox) {
- var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
+ beginDrawing: function CanvasGraphics_beginDrawing(viewport) {
+ var transform = viewport.transform;
this.ctx.save();
- switch (mediaBox.rotate) {
- case 0:
- this.ctx.transform(1, 0, 0, -1, 0, ch);
- break;
- case 90:
- this.ctx.transform(0, 1, 1, 0, 0, 0);
- break;
- case 180:
- this.ctx.transform(-1, 0, 0, 1, cw, 0);
- break;
- case 270:
- this.ctx.transform(0, -1, -1, 0, cw, ch);
- break;
- }
- // Scale so that canvas units are the same as PDF user space units
- this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height);
- // Move the media left-top corner to the (0,0) canvas position
- this.ctx.translate(-mediaBox.x, -mediaBox.y);
+ this.ctx.transform.apply(this.ctx, transform);
if (this.textLayer)
this.textLayer.beginLayout();
return shadow(this, 'mediaBox', obj);
},
get view() {
+ var mediaBox = this.mediaBox;
var cropBox = this.inheritPageProp('CropBox');
- var view = {
- x: 0,
- y: 0,
- width: this.width,
- height: this.height
- };
if (!isArray(cropBox) || cropBox.length !== 4)
- return shadow(this, 'view', view);
-
- var mediaBox = this.mediaBox;
- var offsetX = mediaBox[0], offsetY = mediaBox[1];
+ return shadow(this, 'view', mediaBox);
// From the spec, 6th ed., p.963:
// "The crop, bleed, trim, and art boxes should not ordinarily
// effectively reduced to their intersection with the media box."
cropBox = Util.intersect(cropBox, mediaBox);
if (!cropBox)
- return shadow(this, 'view', view);
+ return shadow(this, 'view', mediaBox);
- var tl = this.rotatePoint(cropBox[0] - offsetX, cropBox[1] - offsetY);
- var br = this.rotatePoint(cropBox[2] - offsetX, cropBox[3] - offsetY);
- view.x = Math.min(tl.x, br.x);
- view.y = Math.min(tl.y, br.y);
- view.width = Math.abs(tl.x - br.x);
- view.height = Math.abs(tl.y - br.y);
-
- return shadow(this, 'view', view);
+ return shadow(this, 'view', cropBox);
},
get annotations() {
return shadow(this, 'annotations', this.inheritPageProp('Annots'));
},
- get width() {
- var mediaBox = this.mediaBox;
- var rotate = this.rotate;
- var width;
- if (rotate == 0 || rotate == 180) {
- width = (mediaBox[2] - mediaBox[0]);
- } else {
- width = (mediaBox[3] - mediaBox[1]);
- }
- return shadow(this, 'width', width);
- },
- get height() {
- var mediaBox = this.mediaBox;
- var rotate = this.rotate;
- var height;
- if (rotate == 0 || rotate == 180) {
- height = (mediaBox[3] - mediaBox[1]);
- } else {
- height = (mediaBox[2] - mediaBox[0]);
- }
- return shadow(this, 'height', height);
- },
get rotate() {
var rotate = this.inheritPageProp('Rotate') || 0;
// Normalize rotation so it's a multiple of 90 and between 0 and 270
);
},
- display: function Page_display(gfx, callback) {
+ display: function Page_display(gfx, viewport, callback) {
var stats = this.stats;
stats.time('Rendering');
var xref = this.xref;
gfx.xref = xref;
gfx.res = resources;
- gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
- width: this.width,
- height: this.height,
- rotate: this.rotate });
+ gfx.beginDrawing(viewport);
var startIdx = 0;
var length = this.operatorList.fnArray.length;
}
next();
},
- rotatePoint: function Page_rotatePoint(x, y, reverse) {
- var rotate = reverse ? (360 - this.rotate) : this.rotate;
- switch (rotate) {
- case 180:
- return {x: this.width - x, y: y};
- case 90:
- return {x: this.width - y, y: this.height - x};
- case 270:
- return {x: y, y: x};
- case 360:
- case 0:
- default:
- return {x: x, y: this.height - y};
- }
- },
getLinks: function Page_getLinks() {
var links = [];
var annotations = pageGetAnnotations();
if (!isName(subtype))
continue;
var rect = annotation.get('Rect');
- var topLeftCorner = this.rotatePoint(rect[0], rect[1]);
- var bottomRightCorner = this.rotatePoint(rect[2], rect[3]);
var item = {};
item.type = subtype.name;
- item.x = Math.min(topLeftCorner.x, bottomRightCorner.x);
- item.y = Math.min(topLeftCorner.y, bottomRightCorner.y);
- item.width = Math.abs(topLeftCorner.x - bottomRightCorner.x);
- item.height = Math.abs(topLeftCorner.y - bottomRightCorner.y);
+ item.rect = rect;
switch (subtype.name) {
case 'Link':
var a = annotation.get('A');
}
return items;
},
- startRendering: function Page_startRendering(ctx, callback, textLayer) {
+ startRendering: function Page_startRendering(ctx, viewport,
+ callback, textLayer) {
var stats = this.stats;
stats.time('Overall');
// If there is no displayReadyPromise yet, then the operatorList was never
function pageDisplayReadyPromise() {
var gfx = new CanvasGraphics(ctx, this.objs, textLayer);
try {
- this.display(gfx, callback);
+ this.display(gfx, viewport, callback);
} catch (e) {
if (callback)
callback(e);
return [xt, yt];
};
+ Util.applyInverseTransform = function Util_applyTransform(p, m) {
+ var d = m[0] * m[3] - m[1] * m[2];
+ var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+ var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+ return [xt, yt];
+ };
+
+ Util.inverseTransform = function Util_inverseTransform(m) {
+ var d = m[0] * m[3] - m[1] * m[2];
+ return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d,
+ (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
+ };
+
// Apply a generic 3d matrix M on a 3-vector v:
// | a b c | | X |
// | d e f | x | Y |
}
return result;
- }
+ };
Util.sign = function Util_sign(num) {
return num < 0 ? -1 : 1;
return Util;
})();
+var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
+ function PageViewport(viewBox, scale, rotate, offsetX, offsetY) {
+ // creating transform to convert pdf coordinate system to the normal
+ // canvas like coordinates taking in account scale and rotation
+ var centerX = (viewBox[2] + viewBox[0]) / 2;
+ var centerY = (viewBox[3] + viewBox[1]) / 2;
+ var rotateA, rotateB, rotateC, rotateD;
+ switch (rotate) {
+ case -180:
+ case 180:
+ rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
+ break;
+ case -270:
+ case 90:
+ rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
+ break;
+ case -90:
+ case 270:
+ rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
+ break;
+ case 360:
+ case 0:
+ default:
+ rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
+ break;
+ }
+ var offsetCanvasX, offsetCanvasY;
+ var width, height;
+ if (rotateA == 0) {
+ offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
+ width = Math.abs(viewBox[3] - viewBox[1]) * scale;
+ height = Math.abs(viewBox[2] - viewBox[0]) * scale;
+ } else {
+ offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
+ width = Math.abs(viewBox[2] - viewBox[0]) * scale;
+ height = Math.abs(viewBox[3] - viewBox[1]) * scale;
+ }
+ // creating transform for the following operations:
+ // translate(-centerX, -centerY), rotate and flip vertically,
+ // scale, and translate(offsetCanvasX, offsetCanvasY)
+ this.transform = [
+ rotateA * scale,
+ rotateB * scale,
+ rotateC * scale,
+ rotateD * scale,
+ offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
+ offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
+ ];
+
+ this.offsetX = offsetX;
+ this.offsetY = offsetY;
+ this.width = width;
+ this.height = height;
+ }
+ PageViewport.prototype = {
+ convertPointToViewport: function PageViewport_convertPointToViewport(x, y) {
+ return Util.applyTransform([x, y], this.transform);
+ },
+ convertRectangleToViewport:
+ function PageViewport_convertRectangeToViewport(rect) {
+ var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
+ var br = Util.applyTransform([rect[2], rect[3]], this.transform);
+ return [tl[0], tl[1], br[0], br[1]];
+ },
+ convertViewportToPoint: function PageViewport_convertViewportToPoint(x, y) {
+ return Util.applyInverseTransform([x, y], this.transform);
+ }
+ };
+ return PageViewport;
+})();
+
var PDFStringTranslateTable = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
var destRef = dest[0];
var pageNumber = destRef instanceof Object ?
this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : (destRef + 1);
+ if (pageNumber > this.pages.length)
+ pageNumber = this.pages.length;
if (pageNumber) {
this.page = pageNumber;
var currentPage = this.pages[pageNumber - 1];
pagesPromise.then(function(promisedPages) {
for (var i = 1; i <= pagesCount; i++) {
var page = promisedPages[i - 1];
- var pageView = new PageView(container, page, i, page.width, page.height,
+ var pageView = new PageView(container, page, i, scale,
page.stats, self.navigateTo.bind(self));
- var thumbnailView = new ThumbnailView(sidebar, page, i,
- page.width / page.height);
+ var thumbnailView = new ThumbnailView(sidebar, page, i);
bindOnAfterDraw(pageView, thumbnailView);
pages.push(pageView);
var windowTop = window.pageYOffset;
for (var i = 1; i <= pages.length; ++i) {
var page = pages[i - 1];
- var pageHeight = page.height * page.scale + kBottomMargin;
+ var pageHeight = page.height + kBottomMargin;
if (currentHeight + pageHeight > windowTop)
break;
}
};
-var PageView = function pageView(container, pdfPage, id, pageWidth, pageHeight,
+var PageView = function pageView(container, pdfPage, id, scale,
stats, navigateTo) {
this.id = id;
this.pdfPage = pdfPage;
- var view = pdfPage.view;
- this.x = view.x;
- this.y = view.y;
- this.width = view.width;
- this.height = view.height;
+ this.scale = scale || 1.0;
+ this.viewport = this.pdfPage.getViewport(scale);
var anchor = document.createElement('a');
anchor.name = '' + this.id;
this.update = function pageViewUpdate(scale) {
this.scale = scale || this.scale;
- div.style.width = (this.width * this.scale) + 'px';
- div.style.height = (this.height * this.scale) + 'px';
+ var viewport = this.pdfPage.getViewport(this.scale);
+
+ this.viewport = viewport;
+ this.width = viewport.width;
+ this.height = viewport.height;
+ div.style.width = viewport.width + 'px';
+ div.style.height = viewport.height + 'px';
while (div.hasChildNodes())
div.removeChild(div.lastChild);
div.appendChild(this.loadingIconDiv);
};
- function setupAnnotations(pdfPage, scale) {
+ function setupAnnotations(pdfPage, viewport) {
function bindLink(link, dest) {
link.href = PDFView.getDestinationHash(dest);
link.onclick = function pageViewSetupLinksOnclick() {
};
}
function createElementWithStyle(tagName, item) {
+ var rect = viewport.convertRectangleToViewport(item.rect);
+ rect = Util.normalizeRect(rect);
var element = document.createElement(tagName);
- element.style.left = (Math.floor(item.x - view.x) * scale) + 'px';
- element.style.top = (Math.floor(item.y - view.y) * scale) + 'px';
- element.style.width = Math.ceil(item.width * scale) + 'px';
- element.style.height = Math.ceil(item.height * scale) + 'px';
+ element.style.left = Math.floor(rect[0]) + 'px';
+ element.style.top = Math.floor(rect[1]) + 'px';
+ element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
+ element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
return element;
}
function createCommentAnnotation(type, item) {
this.getPagePoint = function pageViewGetPagePoint(x, y) {
var scale = PDFView.currentScale;
- return this.pdfPage.rotatePoint(x / scale, y / scale);
+ return this.viewport.convertPointToViewport(x, y);
};
this.scrollIntoView = function pageViewScrollIntoView(dest) {
}
var boundingRect = [
- this.pdfPage.rotatePoint(x, y),
- this.pdfPage.rotatePoint(x + width, y + height)
+ this.viewport.convertPointToViewport(x, y),
+ this.viewport.convertPointToViewport(x + width, y + height)
];
if (scale && scale !== PDFView.currentScale)
setTimeout(function pageViewScrollIntoViewRelayout() {
// letting page to re-layout before scrolling
var scale = PDFView.currentScale;
- var x = Math.min(boundingRect[0].x, boundingRect[1].x);
- var y = Math.min(boundingRect[0].y, boundingRect[1].y);
- var width = Math.abs(boundingRect[0].x - boundingRect[1].x);
- var height = Math.abs(boundingRect[0].y - boundingRect[1].y);
+ var x = Math.min(boundingRect[0][0], boundingRect[1][0]);
+ var y = Math.min(boundingRect[0][1], boundingRect[1][1]);
+ var width = Math.abs(boundingRect[0][0] - boundingRect[1][0]);
+ var height = Math.abs(boundingRect[0][1] - boundingRect[1][1]);
// using temporary div to scroll it into view
var tempDiv = document.createElement('div');
tempDiv.style.position = 'absolute';
- tempDiv.style.left = Math.floor(x * scale) + 'px';
- tempDiv.style.top = Math.floor(y * scale) + 'px';
- tempDiv.style.width = Math.ceil(width * scale) + 'px';
- tempDiv.style.height = Math.ceil(height * scale) + 'px';
+ tempDiv.style.left = Math.floor(x) + 'px';
+ tempDiv.style.top = Math.floor(y) + 'px';
+ tempDiv.style.width = Math.ceil(width) + 'px';
+ tempDiv.style.height = Math.ceil(height) + 'px';
div.appendChild(tempDiv);
tempDiv.scrollIntoView(true);
div.removeChild(tempDiv);
}
var textLayer = textLayerDiv ? new TextLayerBuilder(textLayerDiv) : null;
- var scale = this.scale;
- canvas.width = pageWidth * scale;
- canvas.height = pageHeight * scale;
+ var scale = this.scale, viewport = this.viewport;
+ canvas.width = viewport.width;
+ canvas.height = viewport.height;
var ctx = canvas.getContext('2d');
ctx.save();
ctx.fillStyle = 'rgb(255, 255, 255)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();
- ctx.translate(-this.x * scale, -this.y * scale);
// Rendering area
var renderContext = {
canvasContext: ctx,
+ viewport: this.viewport,
textLayer: textLayer
};
this.pdfPage.render(renderContext).then(
}
);
- setupAnnotations(this.pdfPage, this.scale);
+ setupAnnotations(this.pdfPage, this.viewport);
div.setAttribute('data-loaded', true);
};
};
};
-var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
+var ThumbnailView = function thumbnailView(container, pdfPage, id) {
var anchor = document.createElement('a');
anchor.href = PDFView.getAnchorUrl('#page=' + id);
anchor.onclick = function stopNivigation() {
return false;
};
- var view = page.view;
- this.width = view.width;
- this.height = view.height;
+ var viewport = pdfPage.getViewport(1);
+ var pageWidth = viewport.width;
+ var pageHeight = viewport.height;
+ var pageRatio = pageWidth / pageHeight;
this.id = id;
var maxThumbSize = 134;
maxThumbSize * pageRatio;
var canvasHeight = pageRatio <= 1 ? maxThumbSize :
maxThumbSize / pageRatio;
- var scaleX = this.scaleX = (canvasWidth / this.width);
- var scaleY = this.scaleY = (canvasHeight / this.height);
+ var scaleX = this.scaleX = (canvasWidth / pageWidth);
+ var scaleY = this.scaleY = (canvasHeight / pageHeight);
var div = document.createElement('div');
div.id = 'thumbnailContainer' + id;
var ctx = canvas.getContext('2d');
ctx.save();
ctx.fillStyle = 'rgb(255, 255, 255)';
- ctx.fillRect(0, 0, canvas.width, canvas.height);
+ ctx.fillRect(0, 0, canvasWidth, canvasHeight);
ctx.restore();
-
- var view = page.view;
- ctx.translate(-view.x * scaleX, -view.y * scaleY);
- div.style.width = (view.width * scaleX) + 'px';
- div.style.height = (view.height * scaleY) + 'px';
- div.style.lineHeight = (view.height * scaleY) + 'px';
-
return ctx;
}
}
var ctx = getPageDrawContext();
- page.startRendering(ctx, function thumbnailViewDrawStartRendering() {
- callback();
- });
+ var drawViewport = pdfPage.getViewport(scaleX);
+ page.startRendering(ctx, drawViewport,
+ function thumbnailViewDrawStartRendering() {
+ callback();
+ });
this.hasImage = true;
};
var currentPage = PDFView.pages[pageNumber - 1];
var topLeft = currentPage.getPagePoint(window.pageXOffset,
window.pageYOffset - firstPage.y - kViewerTopMargin);
- pdfOpenParams += ',' + Math.round(topLeft.x) + ',' + Math.round(topLeft.y);
+ pdfOpenParams += ',' + Math.round(topLeft[0]) + ',' + Math.round(topLeft[1]);
var store = PDFView.store;
store.set('exists', true);