mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-01 20:07:22 +02:00
Merge pull request #21666 from calixteman/bug2054348
Fix the selection rendering when a page has been destroyed and rendered again (bug 2054348)
This commit is contained in:
commit
a80897dc9a
@ -641,7 +641,8 @@ class DrawLayer {
|
|||||||
textLayerData.selectionDiv = div;
|
textLayerData.selectionDiv = div;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!div.parentNode && drawLayer.#parent) {
|
if (drawLayer.#parent && div.parentNode !== drawLayer.#parent) {
|
||||||
|
// The div can still be in a canvas wrapper which has been removed.
|
||||||
drawLayer.#parent.append(div);
|
drawLayer.#parent.append(div);
|
||||||
this.#selections.add(div);
|
this.#selections.add(div);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,9 +20,11 @@
|
|||||||
import {
|
import {
|
||||||
closePages,
|
closePages,
|
||||||
closeSinglePage,
|
closeSinglePage,
|
||||||
|
firstPageOnTop,
|
||||||
getSpanRectFromText,
|
getSpanRectFromText,
|
||||||
kbSelectAll,
|
kbSelectAll,
|
||||||
loadAndWait,
|
loadAndWait,
|
||||||
|
scrollIntoView,
|
||||||
waitForEvent,
|
waitForEvent,
|
||||||
} from "./test_utils.mjs";
|
} from "./test_utils.mjs";
|
||||||
import { MathClamp } from "../../src/shared/math_clamp.js";
|
import { MathClamp } from "../../src/shared/math_clamp.js";
|
||||||
@ -1148,6 +1150,94 @@ describe("Text layer", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("when the page has been destroyed and rendered again", () => {
|
||||||
|
const selectionSelector = ".canvasWrapper .selection svg path[d]";
|
||||||
|
const timeout = 5000;
|
||||||
|
|
||||||
|
let pages;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
pages = await loadAndWait(
|
||||||
|
"tracemonkey.pdf",
|
||||||
|
`.page[data-page-number = "1"] .endOfContent`,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{ annotationEditorMode: -1 }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await closePages(pages);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function selectSomeText(page) {
|
||||||
|
const [positionStart, positionEnd] = await Promise.all([
|
||||||
|
getSpanRectFromText(
|
||||||
|
page,
|
||||||
|
1,
|
||||||
|
"(frequently executed) bytecode sequences, records"
|
||||||
|
).then(middlePosition),
|
||||||
|
getSpanRectFromText(
|
||||||
|
page,
|
||||||
|
1,
|
||||||
|
"them, and compiles them to fast native code. We call such a se-"
|
||||||
|
).then(belowEndPosition),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await page.mouse.move(positionStart.x, positionStart.y);
|
||||||
|
await page.mouse.down();
|
||||||
|
await moveInSteps(page, positionStart, positionEnd, 20);
|
||||||
|
await page.mouse.up();
|
||||||
|
}
|
||||||
|
|
||||||
|
it("must draw the selection", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await selectSomeText(page);
|
||||||
|
await page.waitForSelector(selectionSelector, { timeout });
|
||||||
|
|
||||||
|
await page.evaluate(() => {
|
||||||
|
document.getSelection().removeAllRanges();
|
||||||
|
});
|
||||||
|
await page.waitForSelector(selectionSelector, {
|
||||||
|
hidden: true,
|
||||||
|
timeout,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Scroll down, page by page, until the first page view is
|
||||||
|
// evicted from the buffer: its canvas wrapper is then removed.
|
||||||
|
const pagesCount = await page.evaluate(
|
||||||
|
() => window.PDFViewerApplication.pagesCount
|
||||||
|
);
|
||||||
|
let isDestroyed = false;
|
||||||
|
for (let i = 2; i <= pagesCount && !isDestroyed; i++) {
|
||||||
|
const selector = `.page[data-page-number = "${i}"]`;
|
||||||
|
await scrollIntoView(page, selector);
|
||||||
|
await page.waitForSelector(
|
||||||
|
`${selector} .canvasWrapper canvas`,
|
||||||
|
{ timeout: 0 }
|
||||||
|
);
|
||||||
|
isDestroyed = !(await page.$(
|
||||||
|
`.page[data-page-number = "1"] .canvasWrapper`
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(isDestroyed)
|
||||||
|
.withContext(`In ${browserName}, first page destroyed`)
|
||||||
|
.toBeTrue();
|
||||||
|
|
||||||
|
await firstPageOnTop(page);
|
||||||
|
await page.waitForSelector(
|
||||||
|
`.page[data-page-number = "1"] .canvasWrapper canvas`,
|
||||||
|
{ timeout: 0 }
|
||||||
|
);
|
||||||
|
await selectSomeText(page);
|
||||||
|
await page.waitForSelector(selectionSelector, { timeout });
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("using selection carets", () => {
|
describe("using selection carets", () => {
|
||||||
|
|||||||
@ -370,6 +370,7 @@ const PDFViewerApplication = {
|
|||||||
// Set some specific preferences for tests.
|
// Set some specific preferences for tests.
|
||||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||||
Object.assign(opts, {
|
Object.assign(opts, {
|
||||||
|
annotationEditorMode: x => parseInt(x, 10),
|
||||||
capCanvasAreaFactor: x => parseInt(x, 10),
|
capCanvasAreaFactor: x => parseInt(x, 10),
|
||||||
docBaseUrl: x => x,
|
docBaseUrl: x => x,
|
||||||
enableAltText: x => x === "true",
|
enableAltText: x => x === "true",
|
||||||
|
|||||||
@ -936,9 +936,14 @@ class PDFPageView extends BasePDFPageView {
|
|||||||
if (this.structTreeLayer && !this.textLayer) {
|
if (this.structTreeLayer && !this.textLayer) {
|
||||||
this.structTreeLayer = null;
|
this.structTreeLayer = null;
|
||||||
}
|
}
|
||||||
|
// The annotation editor layer and the draw layer keep references on the
|
||||||
|
// text layer (the latter uses its div in order to render the selection),
|
||||||
|
// hence they must be recreated too.
|
||||||
if (
|
if (
|
||||||
this.annotationEditorLayer &&
|
this.annotationEditorLayer &&
|
||||||
(!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)
|
(!keepAnnotationEditorLayer ||
|
||||||
|
!this.annotationEditorLayer.div ||
|
||||||
|
!this.textLayer)
|
||||||
) {
|
) {
|
||||||
if (this.drawLayer) {
|
if (this.drawLayer) {
|
||||||
this.drawLayer.cancel();
|
this.drawLayer.cancel();
|
||||||
@ -947,6 +952,10 @@ class PDFPageView extends BasePDFPageView {
|
|||||||
this.annotationEditorLayer.cancel();
|
this.annotationEditorLayer.cancel();
|
||||||
this.annotationEditorLayer = null;
|
this.annotationEditorLayer = null;
|
||||||
}
|
}
|
||||||
|
if (this.drawLayer && !this.textLayer) {
|
||||||
|
this.drawLayer.cancel();
|
||||||
|
this.drawLayer = null;
|
||||||
|
}
|
||||||
if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
|
if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
|
||||||
this.xfaLayer.cancel();
|
this.xfaLayer.cancel();
|
||||||
this.xfaLayer = null;
|
this.xfaLayer = null;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user