sherpal/LaminarSAPUI5Bindings

Colour.fromString does not handle the alpha channel correctly

Closed this issue · 0 comments

sjrd commented

There are two problems:

  1. The default content of a canvas is solid black, so when drawing the color on the canvas the color gets blended with black instead of preserving its color and alpha channel.
  2. The conversion reuses a single Canvas instance across multiple runs, so subsequent runs blend the color with whatever color was drawn last, making it stateful.

Both issues can fixed by adding a line around:

def fromString(colourString: String): Colour = {
ctx.fillStyle = colourString
ctx.fillRect(0, 0, 1, 1)

as follows:

     def fromString(colourString: String): Colour = {
+      ctx.clearRect(0, 0, 1, 1) // reset the single pixel to transparent black
       ctx.fillStyle = colourString
       ctx.fillRect(0, 0, 1, 1)

As an additional improvement, the conversion could use an OffscreenCanvas instead of a real canvas.

Overall, my local workaround reimplementation looks like this:

  private lazy val colorConversionCanvas = new dom.OffscreenCanvas(1, 1)

  private def ui5ColourFromString(colourString: String): ui5.scaladsl.colour.Colour =
    val ctx = colorConversionCanvas.getContext("2d").asInstanceOf[dom.CanvasRenderingContext2D]

    ctx.clearRect(0, 0, 1, 1)
    ctx.fillStyle = colourString
    ctx.fillRect(0, 0, 1, 1)
    val data  = ctx.getImageData(0, 0, 1, 1).data
    val red   = data(0)
    val green = data(1)
    val blue  = data(2)
    val alpha = data(3) / 255.0

    ui5.scaladsl.colour.Colour(red, green, blue, alpha)
  end ui5ColourFromString