mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-20 15:18:08 +02:00
[Editor] Add a new base class to allow to add a drawing in the SVG layer.
This patch makes a clear separation between the way to draw and the editing stuff. It adds a class DrawEditor which should be extended in order to create new drawing tools. As an example, the ink tool has been rewritten in order to use it.
This commit is contained in:
parent
22babd722f
commit
cee65fcd4e
17 changed files with 2560 additions and 1377 deletions
|
@ -649,7 +649,7 @@ class Driver {
|
|||
|
||||
if (task.annotationStorage) {
|
||||
for (const annotation of Object.values(task.annotationStorage)) {
|
||||
const { bitmapName, quadPoints } = annotation;
|
||||
const { bitmapName, quadPoints, paths, outlines } = annotation;
|
||||
if (bitmapName) {
|
||||
promise = promise.then(async doc => {
|
||||
const response = await fetch(
|
||||
|
@ -687,6 +687,36 @@ class Driver {
|
|||
// like IRL (in order to avoid bugs like bug 1907958).
|
||||
annotation.quadPoints = new Float32Array(quadPoints);
|
||||
}
|
||||
if (paths) {
|
||||
for (let i = 0, ii = paths.lines.length; i < ii; i++) {
|
||||
paths.lines[i] = Float32Array.from(
|
||||
paths.lines[i],
|
||||
x => x ?? NaN
|
||||
);
|
||||
}
|
||||
for (let i = 0, ii = paths.points.length; i < ii; i++) {
|
||||
paths.points[i] = Float32Array.from(
|
||||
paths.points[i],
|
||||
x => x ?? NaN
|
||||
);
|
||||
}
|
||||
}
|
||||
if (outlines) {
|
||||
if (Array.isArray(outlines)) {
|
||||
for (let i = 0, ii = outlines.length; i < ii; i++) {
|
||||
outlines[i] = Float32Array.from(outlines[i], x => x ?? NaN);
|
||||
}
|
||||
} else {
|
||||
outlines.outline = Float32Array.from(
|
||||
outlines.outline,
|
||||
x => x ?? NaN
|
||||
);
|
||||
outlines.points = Float32Array.from(
|
||||
outlines.points,
|
||||
x => x ?? NaN
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ describe("Ink Editor", () => {
|
|||
|
||||
await commit(page);
|
||||
|
||||
const rectBefore = await getRect(page, ".inkEditor canvas");
|
||||
const rectBefore = await getRect(page, ".canvasWrapper .draw");
|
||||
|
||||
for (let i = 0; i < 30; i++) {
|
||||
await kbUndo(page);
|
||||
|
@ -126,7 +126,7 @@ describe("Ink Editor", () => {
|
|||
await waitForStorageEntries(page, 1);
|
||||
}
|
||||
|
||||
const rectAfter = await getRect(page, ".inkEditor canvas");
|
||||
const rectAfter = await getRect(page, ".canvasWrapper .draw");
|
||||
|
||||
expect(Math.round(rectBefore.x))
|
||||
.withContext(`In ${browserName}`)
|
||||
|
@ -453,4 +453,118 @@ describe("Ink Editor", () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Drawing must unselect all", () => {
|
||||
let pages;
|
||||
|
||||
beforeAll(async () => {
|
||||
pages = await loadAndWait("empty.pdf", ".annotationEditorLayer");
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await closePages(pages);
|
||||
});
|
||||
|
||||
it("must check that when we start to draw then the editors are unselected", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await switchToInk(page);
|
||||
const rect = await getRect(page, ".annotationEditorLayer");
|
||||
|
||||
let xStart = rect.x + 10;
|
||||
const yStart = rect.y + 10;
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const clickHandle = await waitForPointerUp(page);
|
||||
await page.mouse.move(xStart, yStart);
|
||||
await page.mouse.down();
|
||||
if (i === 1) {
|
||||
expect(await getSelectedEditors(page))
|
||||
.withContext(`In ${browserName}`)
|
||||
.toEqual([]);
|
||||
}
|
||||
await page.mouse.move(xStart + 50, yStart + 50);
|
||||
await page.mouse.up();
|
||||
await awaitPromise(clickHandle);
|
||||
await commit(page);
|
||||
xStart += 70;
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Selected editor must be updated even if the page has been destroyed", () => {
|
||||
let pages;
|
||||
|
||||
beforeAll(async () => {
|
||||
pages = await loadAndWait("tracemonkey.pdf", ".annotationEditorLayer");
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await closePages(pages);
|
||||
});
|
||||
|
||||
it("must check that the color has been changed", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await switchToInk(page);
|
||||
|
||||
const rect = await getRect(page, ".annotationEditorLayer");
|
||||
|
||||
const x = rect.x + 20;
|
||||
const y = rect.y + 20;
|
||||
const clickHandle = await waitForPointerUp(page);
|
||||
await page.mouse.move(x, y);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(x + 50, y + 50);
|
||||
await page.mouse.up();
|
||||
await awaitPromise(clickHandle);
|
||||
|
||||
await commit(page);
|
||||
|
||||
const drawSelector = `.page[data-page-number = "1"] .canvasWrapper .draw`;
|
||||
await page.waitForSelector(drawSelector, { visible: true });
|
||||
let color = await page.evaluate(sel => {
|
||||
const el = document.querySelector(sel);
|
||||
return el.getAttribute("stroke");
|
||||
}, drawSelector);
|
||||
expect(color).toEqual("#000000");
|
||||
|
||||
const oneToFourteen = Array.from(new Array(13).keys(), n => n + 2);
|
||||
for (const pageNumber of oneToFourteen) {
|
||||
await scrollIntoView(
|
||||
page,
|
||||
`.page[data-page-number = "${pageNumber}"]`
|
||||
);
|
||||
}
|
||||
|
||||
const red = "#ff0000";
|
||||
page.evaluate(value => {
|
||||
window.PDFViewerApplication.eventBus.dispatch(
|
||||
"switchannotationeditorparams",
|
||||
{
|
||||
source: null,
|
||||
type: window.pdfjsLib.AnnotationEditorParamsType.INK_COLOR,
|
||||
value,
|
||||
}
|
||||
);
|
||||
}, red);
|
||||
|
||||
const fourteenToOne = Array.from(new Array(13).keys(), n => 13 - n);
|
||||
for (const pageNumber of fourteenToOne) {
|
||||
await scrollIntoView(
|
||||
page,
|
||||
`.page[data-page-number = "${pageNumber}"]`
|
||||
);
|
||||
}
|
||||
await page.waitForSelector(drawSelector, { visible: true });
|
||||
color = await page.evaluate(sel => {
|
||||
const el = document.querySelector(sel);
|
||||
return el.getAttribute("stroke");
|
||||
}, drawSelector);
|
||||
expect(color).toEqual(red);
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8244,24 +8244,44 @@
|
|||
"color": [255, 0, 0],
|
||||
"thickness": 3,
|
||||
"opacity": 1,
|
||||
"paths": [
|
||||
{
|
||||
"bezier": [
|
||||
73, 560.2277710847244, 74.30408044851005, 561.5318515332344,
|
||||
76.89681158113368, 557.7555609512324, 77.5, 557.2277710847244,
|
||||
81.95407020558315, 553.3304596548392, 87.4811839685984,
|
||||
550.8645311043504, 92.5, 547.7277710847244, 97.38795894206055,
|
||||
544.6727967459365, 109.48854351637208, 540.2392275683522, 113.5,
|
||||
"paths": {
|
||||
"lines": [
|
||||
[
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
73,
|
||||
560.2277710847244,
|
||||
74.30408044851005,
|
||||
561.5318515332344,
|
||||
76.89681158113368,
|
||||
557.7555609512324,
|
||||
77.5,
|
||||
557.2277710847244,
|
||||
81.95407020558315,
|
||||
553.3304596548392,
|
||||
87.4811839685984,
|
||||
550.8645311043504,
|
||||
92.5,
|
||||
547.7277710847244,
|
||||
97.38795894206055,
|
||||
544.6727967459365,
|
||||
109.48854351637208,
|
||||
540.2392275683522,
|
||||
113.5,
|
||||
536.2277710847244
|
||||
],
|
||||
"points": [
|
||||
]
|
||||
],
|
||||
"points": [
|
||||
[
|
||||
73, 560.2277710847244, 76.7257911988625, 558.1025687477292,
|
||||
75.5128345111164, 559.4147224528562, 77.5, 557.2277710847244,
|
||||
92.5, 547.7277710847244, 109.21378602219673, 539.2873735223628,
|
||||
103.32868842191223, 542.3364518890394, 113.5, 536.2277710847244
|
||||
]
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"pageIndex": 0,
|
||||
"rect": [71.5, 534.5, 115, 562],
|
||||
"rotation": 0
|
||||
|
@ -8330,22 +8350,37 @@
|
|||
"color": [255, 0, 0],
|
||||
"thickness": 1,
|
||||
"opacity": 1,
|
||||
"paths": [
|
||||
{
|
||||
"bezier": [
|
||||
417.61538461538464, 520.3461538461538, 419.15384615384613,
|
||||
520.3461538461538, 421.0769230769231, 520.3461538461538,
|
||||
423.38461538461536, 520.3461538461538, 425.6923076923077,
|
||||
520.3461538461538, 429.15384615384613, 519.9615384615385,
|
||||
433.7692307692308, 519.1923076923076
|
||||
],
|
||||
"points": [
|
||||
"paths": {
|
||||
"lines": [
|
||||
[
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
417.61538461538464,
|
||||
520.3461538461538,
|
||||
419.15384615384613,
|
||||
520.3461538461538,
|
||||
421.0769230769231,
|
||||
520.3461538461538,
|
||||
423.38461538461536,
|
||||
520.3461538461538,
|
||||
425.6923076923077,
|
||||
520.3461538461538,
|
||||
429.15384615384613,
|
||||
519.9615384615385,
|
||||
433.7692307692308,
|
||||
519.1923076923076
|
||||
]
|
||||
],
|
||||
"points": [
|
||||
[
|
||||
417.61538461538464, 520.3461538461538, 419.15384615384613,
|
||||
520.3461538461538, 425.6923076923077, 520.3461538461538,
|
||||
433.7692307692308, 519.1923076923076
|
||||
]
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"pageIndex": 0,
|
||||
"rect": [
|
||||
417.11538461538464, 510.46153846153845, 434.42307692307696,
|
||||
|
@ -8358,22 +8393,37 @@
|
|||
"color": [0, 255, 0],
|
||||
"thickness": 1,
|
||||
"opacity": 1,
|
||||
"paths": [
|
||||
{
|
||||
"bezier": [
|
||||
449.92307692307696, 526.6538461538462, 449.92307692307696,
|
||||
527.423076923077, 449.6346153846154, 528.8653846153846,
|
||||
449.0576923076924, 530.9807692307693, 448.4807692307693,
|
||||
533.0961538461539, 447.8076923076924, 536.6538461538462,
|
||||
447.0384615384616, 541.6538461538462
|
||||
],
|
||||
"points": [
|
||||
"paths": {
|
||||
"lines": [
|
||||
[
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
449.92307692307696,
|
||||
526.6538461538462,
|
||||
449.92307692307696,
|
||||
527.423076923077,
|
||||
449.6346153846154,
|
||||
528.8653846153846,
|
||||
449.0576923076924,
|
||||
530.9807692307693,
|
||||
448.4807692307693,
|
||||
533.0961538461539,
|
||||
447.8076923076924,
|
||||
536.6538461538462,
|
||||
447.0384615384616,
|
||||
541.6538461538462
|
||||
]
|
||||
],
|
||||
"points": [
|
||||
[
|
||||
449.92307692307696, 526.6538461538462, 449.92307692307696,
|
||||
527.423076923077, 448.4807692307693, 533.0961538461539,
|
||||
447.0384615384616, 541.6538461538462
|
||||
]
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"pageIndex": 0,
|
||||
"rect": [
|
||||
446.5384615384616, 526.1538461538462, 456.92307692307696,
|
||||
|
@ -8386,22 +8436,37 @@
|
|||
"color": [0, 0, 255],
|
||||
"thickness": 1,
|
||||
"opacity": 1,
|
||||
"paths": [
|
||||
{
|
||||
"bezier": [
|
||||
482.8461538461538, 511.6538461538462, 482.07692307692304,
|
||||
511.6538461538462, 480.53846153846155, 511.6538461538462,
|
||||
478.23076923076917, 511.6538461538462, 475.9230769230769,
|
||||
511.6538461538462, 472.46153846153845, 511.6538461538462,
|
||||
467.8461538461538, 511.6538461538462
|
||||
],
|
||||
"points": [
|
||||
"paths": {
|
||||
"lines": [
|
||||
[
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
482.8461538461538,
|
||||
511.6538461538462,
|
||||
482.07692307692304,
|
||||
511.6538461538462,
|
||||
480.53846153846155,
|
||||
511.6538461538462,
|
||||
478.23076923076917,
|
||||
511.6538461538462,
|
||||
475.9230769230769,
|
||||
511.6538461538462,
|
||||
472.46153846153845,
|
||||
511.6538461538462,
|
||||
467.8461538461538,
|
||||
511.6538461538462
|
||||
]
|
||||
],
|
||||
"points": [
|
||||
[
|
||||
482.8461538461538, 511.6538461538462, 482.07692307692304,
|
||||
511.6538461538462, 475.9230769230769, 511.6538461538462,
|
||||
467.8461538461538, 511.6538461538462
|
||||
]
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"pageIndex": 0,
|
||||
"rect": [
|
||||
467.1923076923077, 511.1538461538462, 483.3461538461538,
|
||||
|
@ -8414,22 +8479,37 @@
|
|||
"color": [0, 255, 255],
|
||||
"thickness": 1,
|
||||
"opacity": 1,
|
||||
"paths": [
|
||||
{
|
||||
"bezier": [
|
||||
445.9230769230769, 509.3846153846154, 445.5384615384615,
|
||||
509.3846153846154, 445.15384615384613, 508.1346153846154,
|
||||
444.7692307692307, 505.6346153846154, 444.38461538461536,
|
||||
503.1346153846154, 443.23076923076917, 499.00000000000006,
|
||||
441.30769230769226, 493.2307692307693
|
||||
],
|
||||
"points": [
|
||||
"paths": {
|
||||
"lines": [
|
||||
[
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
445.9230769230769,
|
||||
509.3846153846154,
|
||||
445.5384615384615,
|
||||
509.3846153846154,
|
||||
445.15384615384613,
|
||||
508.1346153846154,
|
||||
444.7692307692307,
|
||||
505.6346153846154,
|
||||
444.38461538461536,
|
||||
503.1346153846154,
|
||||
443.23076923076917,
|
||||
499.00000000000006,
|
||||
441.30769230769226,
|
||||
493.2307692307693
|
||||
]
|
||||
],
|
||||
"points": [
|
||||
[
|
||||
445.9230769230769, 509.3846153846154, 445.5384615384615,
|
||||
509.3846153846154, 444.38461538461536, 503.1346153846154,
|
||||
441.30769230769226, 493.2307692307693
|
||||
]
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"pageIndex": 0,
|
||||
"rect": [
|
||||
436.03846153846155, 492.5769230769231, 446.4230769230769,
|
||||
|
@ -9599,12 +9679,12 @@
|
|||
"color": [53, 228, 47],
|
||||
"thickness": 20,
|
||||
"opacity": 1,
|
||||
"paths": [
|
||||
{
|
||||
"bezier": [279.9183673469388, 477.0105263157895],
|
||||
"points": [279.9183673469388, 477.0105263157895]
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"lines": [
|
||||
[null, null, null, null, 279.9183673469388, 477.0105263157895]
|
||||
],
|
||||
"points": [[279.9183673469388, 477.0105263157895]]
|
||||
},
|
||||
"pageIndex": 0,
|
||||
"rect": [
|
||||
269.9183673469388, 443.93684210526317, 312.9387755102041,
|
||||
|
|
|
@ -4448,21 +4448,54 @@ describe("annotation", function () {
|
|||
thickness: 1,
|
||||
opacity: 1,
|
||||
color: [0, 0, 0],
|
||||
paths: [
|
||||
{
|
||||
bezier: [
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 22, 23, 24, 25, 26, 27,
|
||||
paths: {
|
||||
lines: [
|
||||
[
|
||||
NaN,
|
||||
NaN,
|
||||
NaN,
|
||||
NaN,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
],
|
||||
points: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
},
|
||||
{
|
||||
bezier: [
|
||||
910, 911, 912, 913, 914, 915, 916, 917, 922, 923, 924, 925,
|
||||
926, 927,
|
||||
[
|
||||
NaN,
|
||||
NaN,
|
||||
NaN,
|
||||
NaN,
|
||||
910,
|
||||
911,
|
||||
912,
|
||||
913,
|
||||
914,
|
||||
915,
|
||||
916,
|
||||
917,
|
||||
922,
|
||||
923,
|
||||
924,
|
||||
925,
|
||||
926,
|
||||
927,
|
||||
],
|
||||
points: [91, 92, 93, 94, 95, 96, 97, 98],
|
||||
},
|
||||
],
|
||||
],
|
||||
points: [
|
||||
[1, 2, 3, 4, 5, 6, 7, 8],
|
||||
[91, 92, 93, 94, 95, 96, 97, 98],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
null,
|
||||
|
@ -4482,13 +4515,12 @@ describe("annotation", function () {
|
|||
const appearance = data[1].data;
|
||||
expect(appearance).toEqual(
|
||||
"2 0 obj\n" +
|
||||
"<< /FormType 1 /Subtype /Form /Type /XObject /BBox [12 34 56 78] /Length 129>> stream\n" +
|
||||
"<< /FormType 1 /Subtype /Form /Type /XObject /BBox [12 34 56 78] /Length 127>> stream\n" +
|
||||
"1 w 1 J 1 j\n" +
|
||||
"0 G\n" +
|
||||
"10 11 m\n" +
|
||||
"12 13 14 15 16 17 c\n" +
|
||||
"22 23 24 25 26 27 c\n" +
|
||||
"S\n" +
|
||||
"910 911 m\n" +
|
||||
"912 913 914 915 916 917 c\n" +
|
||||
"922 923 924 925 926 927 c\n" +
|
||||
|
@ -4513,21 +4545,54 @@ describe("annotation", function () {
|
|||
thickness: 1,
|
||||
opacity: 0.12,
|
||||
color: [0, 0, 0],
|
||||
paths: [
|
||||
{
|
||||
bezier: [
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 22, 23, 24, 25, 26, 27,
|
||||
paths: {
|
||||
lines: [
|
||||
[
|
||||
NaN,
|
||||
NaN,
|
||||
NaN,
|
||||
NaN,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
],
|
||||
points: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
},
|
||||
{
|
||||
bezier: [
|
||||
910, 911, 912, 913, 914, 915, 916, 917, 922, 923, 924, 925,
|
||||
926, 927,
|
||||
[
|
||||
NaN,
|
||||
NaN,
|
||||
NaN,
|
||||
NaN,
|
||||
910,
|
||||
911,
|
||||
912,
|
||||
913,
|
||||
914,
|
||||
915,
|
||||
916,
|
||||
917,
|
||||
922,
|
||||
923,
|
||||
924,
|
||||
925,
|
||||
926,
|
||||
927,
|
||||
],
|
||||
points: [91, 92, 93, 94, 95, 96, 97, 98],
|
||||
},
|
||||
],
|
||||
],
|
||||
points: [
|
||||
[1, 2, 3, 4, 5, 6, 7, 8],
|
||||
[91, 92, 93, 94, 95, 96, 97, 98],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
null,
|
||||
|
@ -4547,7 +4612,7 @@ describe("annotation", function () {
|
|||
const appearance = data[1].data;
|
||||
expect(appearance).toEqual(
|
||||
"2 0 obj\n" +
|
||||
"<< /FormType 1 /Subtype /Form /Type /XObject /BBox [12 34 56 78] /Length 136 /Resources " +
|
||||
"<< /FormType 1 /Subtype /Form /Type /XObject /BBox [12 34 56 78] /Length 134 /Resources " +
|
||||
"<< /ExtGState << /R0 << /CA 0.12 /Type /ExtGState>>>>>>>> stream\n" +
|
||||
"1 w 1 J 1 j\n" +
|
||||
"0 G\n" +
|
||||
|
@ -4555,7 +4620,6 @@ describe("annotation", function () {
|
|||
"10 11 m\n" +
|
||||
"12 13 14 15 16 17 c\n" +
|
||||
"22 23 24 25 26 27 c\n" +
|
||||
"S\n" +
|
||||
"910 911 m\n" +
|
||||
"912 913 914 915 916 917 c\n" +
|
||||
"922 923 924 925 926 927 c\n" +
|
||||
|
@ -4581,13 +4645,10 @@ describe("annotation", function () {
|
|||
thickness: 3,
|
||||
opacity: 1,
|
||||
color: [0, 255, 0],
|
||||
paths: [
|
||||
{
|
||||
bezier: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
// Useless in the printing case.
|
||||
points: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
},
|
||||
],
|
||||
paths: {
|
||||
lines: [[NaN, NaN, NaN, NaN, 1, 2, 3, 4, 5, 6, 7, 8]],
|
||||
points: [[1, 2, 3, 4, 5, 6, 7, 8]],
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue