Open drott opened 2 years ago
Ambiguities arise if the extend mode for the ColorLine is pad and the sector from start angle to end angle of the sweep gradient crosses the 0/360 degree angle, for example 315° and 45°.
In that regard, it seems we need to be clearer on the drawing order and the mapping from angle to ColorLine coordinate.
For each position along the circular arc, from start to end in the counter-clockwise direction, a ray from the center outward is painted with the color of the color line at the point where the ray passes through the arc.
Does "start and end" here refer to 0 degres to 360 degrees starting from the positive horizontal x axis? If it does not and refers to start and end angle, then what happens at the other angles?
Using a ColorLine with extend mode pad, and color stop 0 red, 0.5 yellow, 1 blue
, what do we paint in the following situation:
If "from start to end" in the spec means start drawing from 0 degrees (option 1 above) to 360 degrees, and stop offset 0 on the color line is aligned with 315°, and 1 is aligned with 45°, what do we paint at 0 degrees? What coordinate on the Color line doe 0 degrees refer to? Do we start with yellow at 0° fading to blue at 45°, then continue with blue until 360°, or do we start with red, draw almost a full circle, then fade from red to yellow from 315° to 0°?
For code-archeology background, original discussions when adding PaintSweepGradient
in #217 and #253.
For defining where do we start and end drawing from, i.e. what is painted, and what is discarded as overlap, we need to also take into account the definitions of startAngle
and endAngle
being in F2DOT14 * 180.0f
, so the only way precise way to define "full circle" means -2.0
to 0
, i.e. -360
to 0
.
To summarize, we have at least the following issues:
1) The spec text is too strictly tied to the [0,1] interval. Spec text: "but only color values for the range [0, 1] are painted." conflicts with the definition of extend modes and ColorLine
intervals wider than [0, 1] or narrower than [0,1].
2) Overlap or drawing order is not covered accurately in the spec text. The text is not clear on where drawing should start and where it should end: Should it be from 0 to 360 degrees, or from startAngle
to endAngle
- and if the latter, what happens if such a sector is larger than 360? Or if it's less wide than 360° but the ColorLine
stop positions are defined for outside [0, 1] which then need to be drawn? - This lack of drawing order definition also makes it hard to reason what should happen a sector is drawn across the 0° angle - for example from 340° to 20° or when the sector between endAngle and startAngle is wider than 360°.
3) The modulo rules "Start and end angle values can be outside the range [0, 360), and are converted to values within that range by applying a modulus operation." cause sudden discontinuities, which are not desirable. Think variations.
4) Spec text: "then the extend mode is not relevant and may be ignored. " is inconsistent with other gradient definitions and the behaviour and definition of ColorLine
.
We've previously used the CSS and other W3C specs (Compositing) as a reference or blueprint. It helps implementors apply similar concepts or even reuse code.
The relevant sections are: https://drafts.csswg.org/css-images-4/#conic-gradient-syntax and in particular: https://drafts.csswg.org/css-images-4/#conic-color-stops
I suggest to do the following:
startAngle
and endAngle
are defined as F2DOT14
which allows values between -2
1.99993896484375
and our conversion definition is 180° in counter-clockwise degrees per 1.0 of value.
a full circle from 0 degrees can only be defined as -360 to 0, and applying the modulo operation. Removing modulo, as explained above, I suggest to change the conversion to add an offset so that (startAngle + 1) * 180
or in other words startAngle * 180 + 180
. That makes a value -1
0 degrees and +1
360 degrees, thus allowing even room for scaling startAngle and endAngle past 0 and past 360 on both sides. (Alternatively: Map -2
in F2DOT14
to 0° degrees, i.e. offset +2
before multiplication with 180°, or in other words +360°, but then there's no room for putting start angle < 0°).The CSS Images Lvl 4 spec describes this behaviour more intuitively in the following note:
Note: It may be more helpful to think of the gradient line as forming a spiral, where only the segment from 0deg to 360deg is rendered. This avoids any confusion about "overlap" when you have angles outside of the rendered region.
This helps understand how the above changes would make the behaviour more consistent with the other gradient types and the definition of ColorLine
, and covers the open issues listed in the initial list of issues above.
As an additional visualisation: ColorLine
intervals wider or narrower than or outside of [0, 1] can be normalized or scaled to a [0, 1] interval by scaling startAngle
and endAngle
accordingly. I.e. startAngle = 50, endAngle = 100
(sector angle 50°) for a defined interval of [-0.2, 1.2] is equivalent to startAngle = 50 - 0.2 50 = 40, endAngle = 50 + 1.2 50 = 110, and color stops scaled proportionally to [0, 1].
For reference, updated test cases in https://github.com/googlefonts/color-fonts/pull/99/files - with example renderings in https://github.com/googlefonts/color-fonts/pull/99#issuecomment-1117357643 (to be used with caution, work-in-progress).
Summary from virtual f2f (please correct me if anything from the meeting is inaccurately reflected):
https://docs.microsoft.com/en-us/typography/opentype/spec/colr#sweep-gradients
For context, discussion in: https://github.com/BlackFoundryCom/black-renderer/issues/17
I see two main issues:
It's not painted only from "start to end" but it's painted for all rays of the circle from start to (start + 360) degrees. Start is aligned with color stop offset 0, end is aligned with color stop offset 1.
I suggest to remove that or perhaps this whole paragraph? Do we need the definition of the [0,1] range?
The ColorLine rules for extend modes apply, but they do not talk about the [0,1] range, but the defined interval.
In this paragraph, instead we might want to say that the ColorLine extend modes apply for color stops outside the defined interval. Which means, going down to 0 (= start angle) if the ColorLine's first stop offset is > 0, or going up to 360 / ( endAngle - startAngle). What confused me here is: The [0,1] interval is not what is repeated along the circle, the defined interval of the ColorLine defines that.
We may also need to define what happens if the ColorLine stop points + start and end angles would be overlapping along all directions of rays from the center of the sweep outwards.
CC @justvanrossum