mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-07-25 08:27:19 +02:00
Merge pull request #21604 from calixteman/issue21593
Copy the backdrop for non-isolated groups with a soft mask
This commit is contained in:
commit
d314788368
@ -3333,18 +3333,53 @@ class CanvasGraphics {
|
||||
groupCtx.translate(-offsetX, -offsetY);
|
||||
groupCtx.transform(...currentTransform);
|
||||
|
||||
if (
|
||||
!group.isolated &&
|
||||
!group.smask &&
|
||||
inSMaskMode &&
|
||||
group.needsIsolation
|
||||
) {
|
||||
// For non-isolated groups that need isolation and are entered from SMask
|
||||
// mode, copy the current canvas background so that inner blend modes
|
||||
// (e.g. "screen") interact correctly with the background rather than
|
||||
// compositing onto a transparent canvas.
|
||||
// Groups without needsIsolation have no inner blend modes; their content
|
||||
// is composited correctly via the SMask in endGroup without a copy.
|
||||
const needsBackdropCopy =
|
||||
!group.isolated && !group.smask && group.needsIsolation;
|
||||
const replaceBackdrop =
|
||||
needsBackdropCopy &&
|
||||
!inSMaskMode &&
|
||||
savedKnockoutLevel === 0 &&
|
||||
!group.knockout &&
|
||||
!group.isGray &&
|
||||
group.hasSoftMask &&
|
||||
currentCtx.globalAlpha === 1 &&
|
||||
currentCtx.globalCompositeOperation === "source-over" &&
|
||||
this.current.transferMaps === "none";
|
||||
if (needsBackdropCopy && (inSMaskMode || replaceBackdrop)) {
|
||||
// A non-isolated group that needs isolation (because of an inner blend
|
||||
// mode and/or a soft mask) can't use the direct path above, so it
|
||||
// renders on a transparent intermediate canvas. Copy the current
|
||||
// backdrop into it so the inner blend modes (e.g. "multiply", "screen")
|
||||
// interact with the real background instead of transparency; otherwise a
|
||||
// /Multiply highlight, say, would be painted opaquely over the text
|
||||
// behind it, hiding it (bug 1873345 -- same as the direct path, but here
|
||||
// the soft mask forces an intermediate canvas).
|
||||
// This is needed both when entered from SMask mode and at the top level;
|
||||
// a non-isolated subgroup nested inside a knockout group instead gets its
|
||||
// backdrop through the hasInnerBackdrop path in endGroup, so it's
|
||||
// excluded here via savedKnockoutLevel.
|
||||
//
|
||||
// Outside SMask mode the copy is limited to a group that *would* have
|
||||
// qualified for the direct path (source-over, group alpha 1, not
|
||||
// knockout/gray) but was forced onto the intermediate canvas by its soft
|
||||
// mask (`hasSoftMask`). Restricting to that domain keeps the change
|
||||
// surgical:
|
||||
// - Only the soft-mask case is the bug 1873345 gap; a non-isolated
|
||||
// blend group pushed onto the intermediate canvas merely by a
|
||||
// non-default group alpha (no soft mask) is a separate pre-existing
|
||||
// case, left untouched to avoid changing its rendering (issue 13520).
|
||||
// - source-over/alpha 1 let endGroup replace the backdrop region with
|
||||
// the copied-and-updated result; compositing it normally would blend
|
||||
// partially transparent backdrop pixels twice. Under an outer blend
|
||||
// mode the outer blend would combine the backdrop with itself (e.g.
|
||||
// a /Multiply group with an inner soft mask darkens, issue 12798); a
|
||||
// non-1 group alpha would likewise mix the copied backdrop back in.
|
||||
// Those groups keep the transparent canvas and blend against the
|
||||
// real backdrop instead.
|
||||
// - isGray groups are grayscaled wholesale in endGroup, and an
|
||||
// inherited transfer filter (`transferMaps`) would be applied on
|
||||
// write-back, both of which would corrupt the copied backdrop, so
|
||||
// they're excluded too.
|
||||
groupCtx.save();
|
||||
groupCtx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
groupCtx.drawImage(currentCtx.canvas, -offsetX, -offsetY);
|
||||
@ -3413,6 +3448,7 @@ class CanvasGraphics {
|
||||
offsetX,
|
||||
offsetY,
|
||||
hasInnerBackdrop,
|
||||
replaceBackdrop,
|
||||
knockoutMaskEntry,
|
||||
// Per-group scratch pools, lazily filled and freed in endGroup.
|
||||
knockoutTempEntry: null,
|
||||
@ -3566,6 +3602,14 @@ class CanvasGraphics {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (groupMeta.replaceBackdrop) {
|
||||
// "copy" clears the destination outside the source within the
|
||||
// current clip, so limit it to the intermediate canvas bounds.
|
||||
const clip = new Path2D();
|
||||
clip.rect(0, 0, groupCtx.canvas.width, groupCtx.canvas.height);
|
||||
this.ctx.clip(clip);
|
||||
this.ctx.globalCompositeOperation = "copy";
|
||||
}
|
||||
this.ctx.drawImage(groupCtx.canvas, 0, 0);
|
||||
}
|
||||
this.ctx.restore();
|
||||
|
||||
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -947,3 +947,4 @@
|
||||
!issue21579.pdf
|
||||
!saslprep-r6.pdf
|
||||
!jpx_smaskindata.pdf
|
||||
!nonisolated_blend_smask.pdf
|
||||
|
||||
137
test/pdfs/nonisolated_blend_smask.pdf
Normal file
137
test/pdfs/nonisolated_blend_smask.pdf
Normal file
@ -0,0 +1,137 @@
|
||||
%PDF-1.7
|
||||
%âãÏÓ
|
||||
1 0 obj
|
||||
<< /Type /Catalog /Pages 2 0 R >>
|
||||
endobj
|
||||
2 0 obj
|
||||
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
|
||||
endobj
|
||||
3 0 obj
|
||||
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 320 240]
|
||||
/Group << /Type /Group /S /Transparency /CS /DeviceRGB >>
|
||||
/Resources <<
|
||||
/Font << /F1 5 0 R >>
|
||||
/ExtGState << /Half 7 0 R >>
|
||||
/XObject << /FxText 6 0 R /FxAlpha 12 0 R >>
|
||||
>>
|
||||
/Contents 4 0 R >>
|
||||
endobj
|
||||
4 0 obj
|
||||
<< /Length 419 >>
|
||||
stream
|
||||
q
|
||||
/Half gs
|
||||
0.10 0.35 1 rg
|
||||
20 160 120 35 re f
|
||||
180 160 120 35 re f
|
||||
Q
|
||||
BT /F1 17 Tf 0 0 0 rg 48 213 Td (The two blue boxes should match) Tj ET
|
||||
BT /F1 12 Tf 0 0 0 rg 61 140 Td (control) Tj ET
|
||||
BT /F1 12 Tf 0 0 0 rg 203 140 Td (inside group) Tj ET
|
||||
BT /F1 12 Tf 0 0 0 rg 58 108 Td (Original issue: text should stay visible) Tj ET
|
||||
1 1 1 rg
|
||||
10 15 300 80 re f
|
||||
BT /F1 30 Tf 0 0 0 rg 105 39 Td (Hidden) Tj ET
|
||||
/FxText Do
|
||||
/FxAlpha Do
|
||||
endstream
|
||||
endobj
|
||||
5 0 obj
|
||||
<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>
|
||||
endobj
|
||||
6 0 obj
|
||||
<< /Type /XObject /Subtype /Form /FormType 1 /BBox [0 0 320 100]
|
||||
/Group << /Type /Group /S /Transparency /CS /DeviceRGB /I false >>
|
||||
/Resources <<
|
||||
/ExtGState << /Blend 8 0 R /Masked 9 0 R >>
|
||||
/XObject << /Paint 10 0 R >>
|
||||
>> /Length 35 >>
|
||||
stream
|
||||
/Blend gs
|
||||
q /Masked gs /Paint Do Q
|
||||
endstream
|
||||
endobj
|
||||
7 0 obj
|
||||
<< /Type /ExtGState /ca 0.5 /CA 0.5 >>
|
||||
endobj
|
||||
8 0 obj
|
||||
<< /Type /ExtGState /BM /Multiply >>
|
||||
endobj
|
||||
9 0 obj
|
||||
<< /Type /ExtGState /ca 1 /CA 1
|
||||
/SMask << /Type /Mask /S /Alpha /G 11 0 R >> >>
|
||||
endobj
|
||||
10 0 obj
|
||||
<< /Type /XObject /Subtype /Form /FormType 1 /BBox [0 0 320 100]
|
||||
/Group << /Type /Group /S /Transparency /CS /DeviceRGB /I true >>
|
||||
/Resources << >> /Length 36 >>
|
||||
stream
|
||||
0.55 0.35 0.95 rg
|
||||
30 25 260 55 re f
|
||||
endstream
|
||||
endobj
|
||||
11 0 obj
|
||||
<< /Type /XObject /Subtype /Form /FormType 1 /BBox [0 0 320 100]
|
||||
/Group << /Type /Group /S /Transparency /CS /DeviceGray /I true >>
|
||||
/Resources << >> /Length 22 >>
|
||||
stream
|
||||
1 g
|
||||
30 25 260 55 re f
|
||||
endstream
|
||||
endobj
|
||||
12 0 obj
|
||||
<< /Type /XObject /Subtype /Form /FormType 1 /BBox [170 150 310 200]
|
||||
/Group << /Type /Group /S /Transparency /CS /DeviceRGB /I false >>
|
||||
/Resources <<
|
||||
/ExtGState << /Blend 8 0 R /Masked 13 0 R >>
|
||||
/XObject << /Paint 14 0 R >>
|
||||
>> /Length 35 >>
|
||||
stream
|
||||
/Blend gs
|
||||
q /Masked gs /Paint Do Q
|
||||
endstream
|
||||
endobj
|
||||
13 0 obj
|
||||
<< /Type /ExtGState /ca 1 /CA 1
|
||||
/SMask << /Type /Mask /S /Alpha /G 15 0 R >> >>
|
||||
endobj
|
||||
14 0 obj
|
||||
<< /Type /XObject /Subtype /Form /FormType 1 /BBox [170 150 310 200]
|
||||
/Group << /Type /Group /S /Transparency /CS /DeviceRGB /I true >>
|
||||
/Resources << >> /Length 29 >>
|
||||
stream
|
||||
1 0 0 rg
|
||||
170 150 140 50 re f
|
||||
endstream
|
||||
endobj
|
||||
15 0 obj
|
||||
<< /Type /XObject /Subtype /Form /FormType 1 /BBox [170 150 310 200]
|
||||
/Group << /Type /Group /S /Transparency /CS /DeviceGray /I true >>
|
||||
/Resources << >> /Length 1 >>
|
||||
stream
|
||||
|
||||
endstream
|
||||
endobj
|
||||
xref
|
||||
0 16
|
||||
0000000000 65535 f
|
||||
0000000015 00000 n
|
||||
0000000064 00000 n
|
||||
0000000121 00000 n
|
||||
0000000434 00000 n
|
||||
0000000904 00000 n
|
||||
0000000974 00000 n
|
||||
0000001306 00000 n
|
||||
0000001360 00000 n
|
||||
0000001412 00000 n
|
||||
0000001514 00000 n
|
||||
0000001755 00000 n
|
||||
0000001983 00000 n
|
||||
0000002321 00000 n
|
||||
0000002424 00000 n
|
||||
0000002662 00000 n
|
||||
trailer
|
||||
<< /Size 16 /Root 1 0 R >>
|
||||
startxref
|
||||
2872
|
||||
%%EOF
|
||||
@ -14501,5 +14501,12 @@
|
||||
"md5": "f7a8628b14ca176700247f106c16812a",
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{
|
||||
"id": "nonisolated_blend_smask",
|
||||
"file": "pdfs/nonisolated_blend_smask.pdf",
|
||||
"md5": "4b87611416be34894eeb19c158fafbad",
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
}
|
||||
]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user