Skip to content

Commit 81f14dd

Browse files
committed
Add context style interception for color blending in transparency groups
1 parent fa10cc3 commit 81f14dd

2 files changed

Lines changed: 47 additions & 0 deletions

File tree

src/display/blender/blender.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,47 @@ class Blender {
6666
};
6767
}
6868

69+
/**
70+
* Sets up fillStyle/strokeStyle interceptors on an external (group) context
71+
* so that calcStyle transforms text/shape colors within transparency groups.
72+
*/
73+
interceptGroupStyles(ctx) {
74+
const proto = Object.getPrototypeOf(ctx);
75+
for (const prop of ["fillStyle", "strokeStyle"]) {
76+
const descriptor = Object.getOwnPropertyDescriptor(proto, prop);
77+
const { get: originalGet, set: originalSet } = descriptor;
78+
Object.defineProperty(ctx, prop, {
79+
get: () => originalGet.call(ctx),
80+
set: v => {
81+
originalSet.call(ctx, v);
82+
const currentVal = originalGet.call(ctx);
83+
const newVal = this.getCanvasStyle(currentVal);
84+
if (newVal !== undefined) {
85+
originalSet.call(ctx, newVal);
86+
}
87+
},
88+
configurable: true,
89+
enumerable: true,
90+
});
91+
}
92+
}
93+
94+
/**
95+
* Restores original fillStyle/strokeStyle on a group context.
96+
*/
97+
cleanupGroupStyles(ctx) {
98+
const proto = Object.getPrototypeOf(ctx);
99+
for (const prop of ["fillStyle", "strokeStyle"]) {
100+
const descriptor = Object.getOwnPropertyDescriptor(proto, prop);
101+
Object.defineProperty(ctx, prop, {
102+
get: descriptor.get ? descriptor.get.bind(ctx) : undefined,
103+
set: descriptor.set ? descriptor.set.bind(ctx) : undefined,
104+
configurable: true,
105+
enumerable: true,
106+
});
107+
}
108+
}
109+
69110
/**
70111
* Removes all our property definitions and method wraps on this.ctx.
71112
*/

src/display/canvas.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2927,6 +2927,9 @@ class CanvasGraphics {
29272927
"globalCompositeOperation",
29282928
])
29292929
.pushBaseTransform(currentCtx);
2930+
if (this.blender && !this.blender.forceInversion && !group.smask) {
2931+
this.blender.interceptGroupStyles(this.ctx);
2932+
}
29302933
this.setGState(opIdx, [
29312934
["BM", "source-over"],
29322935
["ca", 1],
@@ -2943,6 +2946,9 @@ class CanvasGraphics {
29432946
}
29442947
this.groupLevel--;
29452948
const groupCtx = this.ctx;
2949+
if (this.blender) {
2950+
this.blender.cleanupGroupStyles(this.ctx);
2951+
}
29462952
const ctx = this.groupStack.pop();
29472953
if (ctx === null) {
29482954
// Simple group: content was drawn directly on the parent canvas.

0 commit comments

Comments
 (0)