Center pages vertically in PresentationMode (issue 10906)

*This patch can be tested e.g. with the `sizes.pdf` document in the test-suite.*

While this patch isn't necessarily the best solution, e.g. it might be possible to solve this with *only* CSS, it's what I was able to come up with to address an old issue.
The solution here re-uses the `spread`-class in PresentationMode, since that one already takes care of centering pages *vertically*, together with a dummy-page that takes up the entire height of the window.

Finally, some PresentationMode-related CSS-rules are also simplified slightly, since the changes in PR 14112 (using Page-scrolling) allows some clean-up here.
This commit is contained in:
Jonas Jenwald 2021-11-23 13:29:00 +01:00
parent 70fc30d97c
commit f7b1da418f
3 changed files with 60 additions and 34 deletions

View File

@ -159,24 +159,14 @@ class PDFPageViewBuffer {
} }
} }
function isSameScale(oldScale, newScale) {
if (newScale === oldScale) {
return true;
}
if (Math.abs(newScale - oldScale) < 1e-15) {
// Prevent unnecessary re-rendering of all pages when the scale
// changes only because of limited numerical precision.
return true;
}
return false;
}
/** /**
* Simple viewer control to display PDF content/pages. * Simple viewer control to display PDF content/pages.
*/ */
class BaseViewer { class BaseViewer {
#buffer = null; #buffer = null;
#previousContainerHeight = 0;
#scrollModePageState = null; #scrollModePageState = null;
/** /**
@ -751,7 +741,20 @@ class BaseViewer {
if (this._spreadMode === SpreadMode.NONE) { if (this._spreadMode === SpreadMode.NONE) {
// Finally, append the new page to the viewer. // Finally, append the new page to the viewer.
const pageView = this._pages[pageNumber - 1]; const pageView = this._pages[pageNumber - 1];
viewer.appendChild(pageView.div);
if (this.isInPresentationMode) {
const spread = document.createElement("div");
spread.className = "spread";
const dummyPage = document.createElement("div");
dummyPage.className = "dummyPage";
dummyPage.style.height = `${this.container.clientHeight}px`;
spread.appendChild(dummyPage);
spread.appendChild(pageView.div);
viewer.appendChild(spread);
} else {
viewer.appendChild(pageView.div);
}
state.pages.push(pageView); state.pages.push(pageView);
} else { } else {
@ -828,10 +831,29 @@ class BaseViewer {
scrollIntoView(pageDiv, pageSpot); scrollIntoView(pageDiv, pageSpot);
} }
/**
* Prevent unnecessary re-rendering of all pages when the scale changes
* only because of limited numerical precision.
*/
#isSameScale(newScale) {
if (
this.isInPresentationMode &&
this.container.clientHeight !== this.#previousContainerHeight
) {
// Ensure that the current page remains centered vertically if/when
// the window is resized while PresentationMode is active.
return false;
}
return (
newScale === this._currentScale ||
Math.abs(newScale - this._currentScale) < 1e-15
);
}
_setScaleUpdatePages(newScale, newValue, noScroll = false, preset = false) { _setScaleUpdatePages(newScale, newValue, noScroll = false, preset = false) {
this._currentScaleValue = newValue.toString(); this._currentScaleValue = newValue.toString();
if (isSameScale(this._currentScale, newScale)) { if (this.#isSameScale(newScale)) {
if (preset) { if (preset) {
this.eventBus.dispatch("scalechanging", { this.eventBus.dispatch("scalechanging", {
source: this, source: this,
@ -886,6 +908,8 @@ class BaseViewer {
if (this.defaultRenderingQueue) { if (this.defaultRenderingQueue) {
this.update(); this.update();
} }
this.#previousContainerHeight = this.container.clientHeight;
} }
/** /**
@ -911,11 +935,15 @@ class BaseViewer {
if (!currentPage) { if (!currentPage) {
return; return;
} }
const noPadding = this.isInPresentationMode || this.removePageBorders; let hPadding = SCROLLBAR_PADDING,
let hPadding = noPadding ? 0 : SCROLLBAR_PADDING; vPadding = VERTICAL_PADDING;
let vPadding = noPadding ? 0 : VERTICAL_PADDING;
if (!noPadding && this._scrollMode === ScrollMode.HORIZONTAL) { if (this.isInPresentationMode) {
hPadding = vPadding = 4;
} else if (this.removePageBorders) {
hPadding = vPadding = 0;
}
if (this._scrollMode === ScrollMode.HORIZONTAL) {
[hPadding, vPadding] = [vPadding, hPadding]; // Swap the padding values. [hPadding, vPadding] = [vPadding, hPadding]; // Swap the padding values.
} }
const pageWidthScale = const pageWidthScale =

View File

@ -17,7 +17,7 @@
@import url(xfa_layer_builder.css); @import url(xfa_layer_builder.css);
:root { :root {
--pdfViewer-padding-bottom: none; --pdfViewer-padding-bottom: 0;
--page-margin: 1px auto -8px; --page-margin: 1px auto -8px;
--page-border: 9px solid transparent; --page-border: 9px solid transparent;
--spreadHorizontalWrapped-margin-LR: -3.5px; --spreadHorizontalWrapped-margin-LR: -3.5px;
@ -55,6 +55,12 @@
background-color: rgba(255, 255, 255, 1); background-color: rgba(255, 255, 255, 1);
} }
.pdfViewer .dummyPage {
position: relative;
width: 0;
/* The height is set via JS, see `BaseViewer.#ensurePageViewVisible`. */
}
.pdfViewer.removePageBorders .page { .pdfViewer.removePageBorders .page {
margin: 0 auto 10px; margin: 0 auto 10px;
border: none; border: none;
@ -90,6 +96,7 @@
} }
.spread .page, .spread .page,
.spread .dummyPage,
.pdfViewer.scrollHorizontal .page, .pdfViewer.scrollHorizontal .page,
.pdfViewer.scrollWrapped .page, .pdfViewer.scrollWrapped .page,
.pdfViewer.scrollHorizontal .spread, .pdfViewer.scrollHorizontal .spread,
@ -135,22 +142,14 @@
} }
.pdfPresentationMode .pdfViewer { .pdfPresentationMode .pdfViewer {
margin-left: 0; padding-bottom: 0;
margin-right: 0;
} }
.pdfPresentationMode .pdfViewer .page, .pdfPresentationMode .spread {
.pdfPresentationMode .pdfViewer .spread { margin: 0;
display: block;
} }
.pdfPresentationMode .pdfViewer .page, .pdfPresentationMode .pdfViewer .page {
.pdfPresentationMode .pdfViewer.removePageBorders .page { margin: 0 auto;
margin-left: auto; border: 2px solid transparent;
margin-right: auto;
}
.pdfPresentationMode:fullscreen .pdfViewer .page {
margin-bottom: 100%;
border: 0;
} }

View File

@ -211,7 +211,6 @@ select {
#viewerContainer.pdfPresentationMode:fullscreen { #viewerContainer.pdfPresentationMode:fullscreen {
top: 0; top: 0;
border-top: 2px solid rgba(0, 0, 0, 0);
background-color: rgba(0, 0, 0, 1); background-color: rgba(0, 0, 0, 1);
width: 100%; width: 100%;
height: 100%; height: 100%;