mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-07-25 16:37:22 +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.translate(-offsetX, -offsetY);
|
||||||
groupCtx.transform(...currentTransform);
|
groupCtx.transform(...currentTransform);
|
||||||
|
|
||||||
if (
|
const needsBackdropCopy =
|
||||||
!group.isolated &&
|
!group.isolated && !group.smask && group.needsIsolation;
|
||||||
!group.smask &&
|
const replaceBackdrop =
|
||||||
inSMaskMode &&
|
needsBackdropCopy &&
|
||||||
group.needsIsolation
|
!inSMaskMode &&
|
||||||
) {
|
savedKnockoutLevel === 0 &&
|
||||||
// For non-isolated groups that need isolation and are entered from SMask
|
!group.knockout &&
|
||||||
// mode, copy the current canvas background so that inner blend modes
|
!group.isGray &&
|
||||||
// (e.g. "screen") interact correctly with the background rather than
|
group.hasSoftMask &&
|
||||||
// compositing onto a transparent canvas.
|
currentCtx.globalAlpha === 1 &&
|
||||||
// Groups without needsIsolation have no inner blend modes; their content
|
currentCtx.globalCompositeOperation === "source-over" &&
|
||||||
// is composited correctly via the SMask in endGroup without a copy.
|
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.save();
|
||||||
groupCtx.setTransform(1, 0, 0, 1, 0, 0);
|
groupCtx.setTransform(1, 0, 0, 1, 0, 0);
|
||||||
groupCtx.drawImage(currentCtx.canvas, -offsetX, -offsetY);
|
groupCtx.drawImage(currentCtx.canvas, -offsetX, -offsetY);
|
||||||
@ -3413,6 +3448,7 @@ class CanvasGraphics {
|
|||||||
offsetX,
|
offsetX,
|
||||||
offsetY,
|
offsetY,
|
||||||
hasInnerBackdrop,
|
hasInnerBackdrop,
|
||||||
|
replaceBackdrop,
|
||||||
knockoutMaskEntry,
|
knockoutMaskEntry,
|
||||||
// Per-group scratch pools, lazily filled and freed in endGroup.
|
// Per-group scratch pools, lazily filled and freed in endGroup.
|
||||||
knockoutTempEntry: null,
|
knockoutTempEntry: null,
|
||||||
@ -3566,6 +3602,14 @@ class CanvasGraphics {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} 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.drawImage(groupCtx.canvas, 0, 0);
|
||||||
}
|
}
|
||||||
this.ctx.restore();
|
this.ctx.restore();
|
||||||
|
|||||||
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -947,3 +947,4 @@
|
|||||||
!issue21579.pdf
|
!issue21579.pdf
|
||||||
!saslprep-r6.pdf
|
!saslprep-r6.pdf
|
||||||
!jpx_smaskindata.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",
|
"md5": "f7a8628b14ca176700247f106c16812a",
|
||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "eq"
|
"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