Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
603 changes: 577 additions & 26 deletions src/display/canvas.js

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions src/display/filter_factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ class BaseFilterFactory {
return "none";
}

addKnockoutFilter(alpha = 0) {
return "none";
}

addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) {
return "none";
}
Expand Down Expand Up @@ -329,6 +333,37 @@ class DOMFilterFactory extends BaseFilterFactory {
return url;
}

addKnockoutFilter(alpha = 0) {
// Shape alpha mask: for translucent elements, remove the opacity constant
// from the painted alpha while preserving antialias coverage. With no
// usable opacity, fall back to a binary mask.
const slope = alpha > 0 ? Math.min(1 / alpha, 1e6) : 1e6;
const key = `knockout_${slope}`;
const value = this.#cache.get(key);
if (value) {
return value;
}

const id = `g_${this.#docId}_knockout_filter_${this.#id++}`;
const url = this.#createUrl(id);
this.#cache.set(key, url);

const filter = this.#createFilter(id);
const feComponentTransfer = this.#document.createElementNS(
SVG_NS,
"feComponentTransfer"
);
filter.append(feComponentTransfer);
const feFuncA = this.#document.createElementNS(SVG_NS, "feFuncA");
// Linear feFunc clamps to [0, 1].
feFuncA.setAttribute("type", "linear");
feFuncA.setAttribute("slope", `${slope}`);
feFuncA.setAttribute("intercept", "0");
feComponentTransfer.append(feFuncA);

return url;
}

addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) {
const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`;
let info = this.#hcmCache.get(filterName);
Expand Down
15 changes: 15 additions & 0 deletions src/shared/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,21 @@ class FeatureTest {
});
}

static get isCanvasFilterSupported() {
let ctx;
if (this.isOffscreenCanvasSupported) {
ctx = new OffscreenCanvas(1, 1).getContext("2d");
} else if (typeof document !== "undefined") {
ctx = document.createElement("canvas").getContext("2d");
}
// Spec-compliant Canvas2D defaults `ctx.filter` to "none". On
// browsers without filter support (Safari) the property is absent
// until you assign to it, after which it behaves like an ordinary
// JS property and stores whatever string you set without applying
// it. Probing the default lets us detect the difference reliably.
return shadow(this, "isCanvasFilterSupported", ctx?.filter !== undefined);
}

static get isAlphaColorInputSupported() {
return shadow(
this,
Expand Down
7 changes: 7 additions & 0 deletions test/pdfs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
!bug1727053.pdf
!issue18408_reduced.pdf
!bug1907000_reduced.pdf
!knockout_blend_multiply.pdf
!knockout_isolated_overlap.pdf
!knockout_nested.pdf
!knockout_nested_group_alpha.pdf
!knockout_nonisolated_sparse.pdf
!knockout_smask.pdf
!SimFang-variant.pdf
!bug1953099.pdf
!issue11913.pdf
Expand Down Expand Up @@ -913,3 +919,4 @@
!smask_alpha_bc.pdf
!smask_luminosity_oob_transfer.pdf
!operator_list_cycle.pdf
!knockout_groups_test.pdf
Binary file added test/pdfs/knockout_blend_multiply.pdf
Binary file not shown.
Binary file added test/pdfs/knockout_groups_test.pdf
Binary file not shown.
Binary file added test/pdfs/knockout_isolated_overlap.pdf
Binary file not shown.
Binary file added test/pdfs/knockout_nested.pdf
Binary file not shown.
Binary file added test/pdfs/knockout_nested_group_alpha.pdf
Binary file not shown.
Binary file added test/pdfs/knockout_nonisolated_sparse.pdf
Binary file not shown.
Binary file added test/pdfs/knockout_smask.pdf
Binary file not shown.
56 changes: 56 additions & 0 deletions test/test_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6740,6 +6740,54 @@
"maxY": 0.5
}
},
{
"id": "knockout_smask",
"file": "pdfs/knockout_smask.pdf",
"md5": "d89fbb623f8e5f200a324607dd30449d",
"rounds": 1,
"type": "eq",
"about": "Knockout group element with an active soft mask."
},
{
"id": "knockout_nested",
"file": "pdfs/knockout_nested.pdf",
"md5": "e3db1591b84f7654d53f553c60ec9fd1",
"rounds": 1,
"type": "eq",
"about": "Nested knockout group used as an element of an outer knockout group."
},
{
"id": "knockout_nested_group_alpha",
"file": "pdfs/knockout_nested_group_alpha.pdf",
"md5": "cec0133fe020f089a73530274c295fcc",
"rounds": 1,
"type": "eq",
"about": "Nested transparency group with parent alpha used as an element of an outer knockout group."
},
{
"id": "knockout_nonisolated_sparse",
"file": "pdfs/knockout_nonisolated_sparse.pdf",
"md5": "6c9837d997785b4d7f848fa7a96ff984",
"rounds": 1,
"type": "eq",
"about": "Sparse non-isolated knockout group under a blend mode."
},
{
"id": "knockout_isolated_overlap",
"file": "pdfs/knockout_isolated_overlap.pdf",
"md5": "b9c5dda6b8c7eb51a904766171290dc0",
"rounds": 1,
"type": "eq",
"about": "Isolated knockout group with two overlapping translucent fills; the overlap area must show only the second fill (no source-over mix)."
},
{
"id": "knockout_blend_multiply",
"file": "pdfs/knockout_blend_multiply.pdf",
"md5": "e0b68fa675e58685fbf1b916fa03e301",
"rounds": 1,
"type": "eq",
"about": "Non-isolated knockout group with a Multiply blend mode element on a yellow backdrop; the element must blend against the backdrop, not against a transparent temp canvas."
},
{
"id": "issue6010_1",
"file": "pdfs/issue6010_1.pdf",
Expand Down Expand Up @@ -14196,5 +14244,13 @@
"md5": "267dc76f33cc0c0b6d36ff4605f60907",
"rounds": 1,
"type": "eq"
},
{
"id": "knockout_groups_test",
"file": "pdfs/knockout_groups_test.pdf",
"md5": "8e085d0dcea38e976f81cbfb50ece6cd",
"rounds": 1,
"type": "eq",
"about": "Knockout groups composite-modes survey."
}
]
Loading