Skip to content

Commit dd6459c

Browse files
Merge pull request #20525 from calixteman/simplify_gradient
Avoid pattern creation with some basic gradients
2 parents f66575a + 4ff582a commit dd6459c

File tree

1 file changed

+65
-11
lines changed

1 file changed

+65
-11
lines changed

src/display/pattern_helper.js

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,51 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
7171
this.matrix = null;
7272
}
7373

74-
_createGradient(ctx) {
74+
isOriginBased() {
75+
return (
76+
this._p0[0] === 0 &&
77+
this._p0[1] === 0 &&
78+
(!this.isRadial() || (this._p1[0] === 0 && this._p1[1] === 0))
79+
);
80+
}
81+
82+
isRadial() {
83+
return this._type === "radial";
84+
}
85+
86+
_createGradient(ctx, transform = null) {
7587
let grad;
88+
let firstPoint = this._p0;
89+
let secondPoint = this._p1;
90+
if (transform) {
91+
firstPoint = firstPoint.slice();
92+
secondPoint = secondPoint.slice();
93+
Util.applyTransform(firstPoint, transform);
94+
Util.applyTransform(secondPoint, transform);
95+
}
7696
if (this._type === "axial") {
7797
grad = ctx.createLinearGradient(
78-
this._p0[0],
79-
this._p0[1],
80-
this._p1[0],
81-
this._p1[1]
98+
firstPoint[0],
99+
firstPoint[1],
100+
secondPoint[0],
101+
secondPoint[1]
82102
);
83103
} else if (this._type === "radial") {
104+
let r0 = this._r0;
105+
let r1 = this._r1;
106+
if (transform) {
107+
const scale = new Float32Array(2);
108+
Util.singularValueDecompose2dScale(transform, scale);
109+
r0 *= scale[0];
110+
r1 *= scale[0];
111+
}
84112
grad = ctx.createRadialGradient(
85-
this._p0[0],
86-
this._p0[1],
87-
this._r0,
88-
this._p1[0],
89-
this._p1[1],
90-
this._r1
113+
firstPoint[0],
114+
firstPoint[1],
115+
r0,
116+
secondPoint[0],
117+
secondPoint[1],
118+
r1
91119
);
92120
}
93121

@@ -100,6 +128,32 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
100128
getPattern(ctx, owner, inverse, pathType) {
101129
let pattern;
102130
if (pathType === PathType.STROKE || pathType === PathType.FILL) {
131+
if (this.isOriginBased()) {
132+
let transf = Util.transform(inverse, owner.baseTransform);
133+
if (this.matrix) {
134+
transf = Util.transform(transf, this.matrix);
135+
}
136+
const precision = 1e-3;
137+
const n1 = Math.hypot(transf[0], transf[1]);
138+
const n2 = Math.hypot(transf[2], transf[3]);
139+
const ps = (transf[0] * transf[2] + transf[1] * transf[3]) / (n1 * n2);
140+
if (Math.abs(ps) < precision) {
141+
// The images of the basis vectors are orthogonal.
142+
if (this.isRadial()) {
143+
// If the images of the basis vectors are a square then the
144+
// circles are transformed to circles and we can use a gradient
145+
// directly.
146+
if (Math.abs(n1 - n2) < precision) {
147+
return this._createGradient(ctx, transf);
148+
}
149+
} else {
150+
// The rectangles are transformed to rectangles and we can use a
151+
// gradient directly.
152+
return this._createGradient(ctx, transf);
153+
}
154+
}
155+
}
156+
103157
const ownerBBox = owner.current.getClippedPathBoundingBox(
104158
pathType,
105159
getCurrentTransform(ctx)

0 commit comments

Comments
 (0)