Merge pull request #21014 from calixteman/issue257

Fix radial gradient when the two circles have an intersection
This commit is contained in:
Tim van der Meij 2026-04-03 20:00:37 +02:00 committed by GitHub
commit a96fb4dbb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 19 additions and 11 deletions

View File

@ -84,21 +84,19 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
return this._type === "radial";
}
// Returns true when the smaller circle's center (p0 when r0 ≤ r1) lies
// outside the larger circle. In that case the canvas radial gradient picks
// t > 1 solutions for points inside the outer circle and maps them to the
// transparent stop we append for extendEnd=false, making the gradient
// invisible. A two-pass draw (reversed first, normal on top) fixes this
// (see #20851).
_isCircleCenterOutside() {
if (!this.isRadial() || this._r0 > this._r1) {
// Return true when the a circle of a radial gradient isn't fully included in
// the other circle, which means that the gradient is conic and we need to
// draw the reversed gradient first to correctly render the pattern (see
// #20851 and #257).
areConic() {
if (!this.isRadial()) {
return false;
}
const dist = Math.hypot(
this._p0[0] - this._p1[0],
this._p0[1] - this._p1[1]
);
return dist > this._r1;
return dist + this._r1 > this._r0 && dist + this._r0 > this._r1;
}
_createGradient(ctx, transform = null) {
@ -242,7 +240,7 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
}
applyBoundingBox(tmpCtx, this._bbox);
if (this._isCircleCenterOutside()) {
if (this.areConic()) {
tmpCtx.fillStyle = this._createReversedGradient(tmpCtx);
tmpCtx.fill();
}
@ -257,7 +255,7 @@ class RadialAxialShadingPattern extends BaseShadingPattern {
// Shading fills are applied relative to the current matrix which is also
// how canvas gradients work, so there's no need to do anything special
// here.
if (this._isCircleCenterOutside()) {
if (this.areConic()) {
// Draw the reversed gradient first so the normal gradient can
// correctly overlay it (see _isCircleCenterOutside for details).
ctx.save();

View File

@ -14042,5 +14042,15 @@
"md5": "7796f0131e7d6428c1bf24a73ff13f95",
"rounds": 1,
"type": "eq"
},
{
"id": "pdfspec-radial-gradient",
"file": "pdfs/pdf.pdf",
"md5": "dbdb23c939d2be09b43126c3c56060c7",
"link": true,
"firstPage": 1144,
"lastPage": 1144,
"rounds": 1,
"type": "eq"
}
]