Palette factory
Scrawl-canvas uses Palette objects to handle color management for its Gradient, RadialGradient and ConicGradient styles.
- Every gradient-type object gets a Palette object as part of its construction, stored in its
palette attribute.
- Developers should never need to interact with Palette objects directly; gradient-type styles include functions for adding and manipulating gradient color stops.
- Packet, clone and kill functionality is also managed through the gradient-type style objects.
Gradients and color stops
The Canvas API uses a rather convoluted way to add color data to a CanvasGradient interface object:
- the object is created first on the <canvas> context engine where it is to be applied, with start and end coordinates,
- then color stops are individually added to it afterwards.
- This needs to be done for every gradient applied to a context engine before any fill or stroke operation using that gradient.
- And only one gradient may be applied to the context engine at any time.
The specificity of the above requirements - in particular relating to position coordinates - and the inability to update the CanvasGradient beyond adding color stops to it, means that storing these objects for future use is not a useful proposition … especially in a dynamic environment where we want the gradient to move in-step with an entity, or animate its colors in some way.
Scrawl-canvas overcomes this problem through the use of Palette objects which separate a gradient-type style’s color-stop data from its positioning data. We treat Canvas API CanvasGradient objects as use-once-and-dispose objects, generating them in a just-in-time fashion for each entity’s stamp operation in the Display cycle.
NOTE – Why Scrawl-canvas HSL/HWB gradients don’t match CSS
Browsers treat hsl() and hwb() as alternate notations of sRGB. For gradients, CSS first resolves all stops to sRGB and then interpolates channels in RGB (premultiplied alpha). Result: CSS gradients for RGB/HSL/HWB look the same.
Scrawl-canvas intentionally interpolates in the declared internal space. For HSL and HWB the code blends the cylindrical components (with shortest-arc hue wrapping), which produces more saturated, “truer HSL/HWB” midpoints than RGB-space blends. That’s why gradients built in the HSL/HWB color space tend to be more colorful, and differ from equivalent CSS gradients.
NOTE – Why Scrawl-canvas LCH/OKLCH gradients don’t match CSS
Most browsers currently render lch() and oklch() gradient stops by converting them to the Cartesian forms (Lab / Oklab) and then interpolating linearly in that space (premultiplied-alpha, then mapped to sRGB). Hue is only used to form a/b (or A/B), it is not interpolated as an angle; achromatic stops effectively collapse to Lab/Oklab vectors. In practice this makes CSS LCH ≈ CSS LAB and CSS OKLCH ≈ CSS OKLAB.
Scrawl-canvas intentionally interpolates in the cylindrical spaces themselves: L linearly; H with shortest-arc wrapping; C linearly, with chroma gently clipped/fit to the output gamut. That preserves hue continuity and tends to produce more saturated “LCH-like / OKLCH-like” midpoints (e.g. a magenta ridge between red→blue), hence the visual difference from equivalent CSS gradients.