W3C home > Mailing lists > Public > public-html@w3.org > February 2008

Re: several messages about radial gradients

From: Philip Taylor <pjt47@cam.ac.uk>
Date: Thu, 14 Feb 2008 14:25:43 +0000
Message-ID: <47B44F67.9060608@cam.ac.uk>
To: Ian Hickson <ian@hixie.ch>
CC: Boris Zbarsky <bzbarsky@MIT.EDU>, "public-html@w3.org" <public-html@w3.org>

Ian Hickson wrote:
>>>> Both SVG behaviours can be emulated using the canvas behaviour. When 
>>>> one circle is inside the other, the canvas behaviour can be emulated 
>>>> using the SVG 1.1 behaviour (with some adjustments to colour stop 
>>>> offsets).
> Philip, can you elaborate on this?

My original thoughts were about how SVG code like:

     <radialGradient cx cy r fx fy>
       <stop offset .../>

could be rendered on canvas approximately like:

     dx = fx-cx, dy = fy-cy
     d = sqrt(dx^2 + dy^2)
     if d > r: # (force the focus point to be inside the circle)
         dx *= 0.999 * r/d
         dy *= 0.999 * r/d
     g = ctx.createRadialGradient(cx+dx, cy+dy, 0, cx, cy, r)
     g.addColorStop(offset, ...)

(ignoring some handling for r<=0, misordered stops, out-of-range stops, 
and all sorts of other complexities).

Canvas code like:

     g = ctx.createRadialGradient(x0, y0, r0, x1, y1, r1)
     g.addColorStop(offset, ...)

(assuming r0 < r1) could be rendered to SVG approximately like:

     d = sqrt((x1-x0)^2 + (y1-y0)^2)
     <radialGradient cx={x1} cy={y1} r={r1} fx={x0} fy={y0}>
       <stop offset={r0/d + (1-r0/d)*offset} .../>

iff (x0,y0,r0) is contained within (x1,y1,r1). If it's not contained 
within, then it has the weird canvas cone behaviour and can't be 
approximated by an SVG gradient (because SVG forces the focus point to 
be inside the circle, exactly to avoid the situations where you'd have 
to draw a weird cone or something).

I'm not sure that's particularly relevant to anything, though.

SVG and canvas can never be exactly the same, because SVG has 
circle-plus-focus-point while canvas has outer-circle-plus-inner-circle. 
Code sharing should (and does) occur in the low-level rendering code 
(Cairo, Quartz, etc), not in the browser API code (SVG, canvas).

I think the relevant issue is that the various low-level rendering 
libraries (and the different versions of those libraries, and the 
different backends within each version) are sufficiently interoperable 
for SVG but not for canvas, and it is significantly easier for 
implementors if we fix that by changing canvas to only use the 
interoperable subset of those libraries (by forcing the smaller circle 
to be contained within the larger circle, which just requires a few 
extra calculations in the canvas API implementation), rather than 
requiring changes inside those libraries.

Philip Taylor
Received on Thursday, 14 February 2008 14:26:02 UTC

This archive was generated by hypermail 2.4.0 : Saturday, 9 October 2021 18:44:26 UTC