Acknowledged

Creating Full White Color Results in Transparent

We might expect this code to draw a filled white circle:

var testWhite = Graphics.createColor(0xFF, 0xFF, 0xFF, 0xFF);
dc.setFill(testWhite);
dc.fillCircle(halfScreenWidth, halfScreenHeight, 10);

However, what actually happens is nothing is drawn. This is because Graphics.createColor translates the color to 0xFFFFFFFF, which is -1 in twos complement, and which is the same as Graphics.COLOR_TRANSPARENT. Changing e.g. the alpha value to 0xFE instead of 0xFF will cause the circle to draw as expected.

  • Great find!

    TL;DR a related (and seemingly unsolvable) issue is that setting an alpha channel / opacity of 0 will have the opposite of the intended effect - the resulting color will be completely opaque.

    --

    Not to state the obvious, but this bug stems from the fact that all the CIQ API calls which produce or accept a color define a color value as Lang.Number (signed 32-bit). Conceivably, one way to fix this would be to use Lang.Long (signed-64 bit) instead, but ofc that would break backwards compatibility and lead to other issues (the memory usage for an array of Longs is much worse than the usage for an array of Numbers, for example.)

    Or Graphics.createColor() could be changed so that given an input of (0xff, 0xff, 0xff, 0xff), it returns 0xFFFFFF (as if the alpha value was 0.) Note that Graphics.COLOR_WHITE is 0xFFFFFF.

    This leads to another issue though - setting an alpha channel of 0 will not have the expected result.

    Logically, setting the alpha channel to 0 in the call to Graphics.createColor() should lead to a completely transparent color (same as effect as using COLOR_TRANSPARENT), but it actually seems to have the opposite effect: you get a completely opaque color instead.

    Again not to state the obvious but it seems that this problem stems from Garmin deciding to use both RGB and ARGB formats simultaneously, so that the alpha channel is in the most significant byte of the color, meaning that the underlying value of RGB(0xff, 0, 0) (red) is the same as ARGB(opacity = 0, 0xff, 0, 0) (red but completely transparent.) IOW, there is no way to distinguish between an RGB value and the corresponding ARGB value where the opacity happens to be 0.

    (Ofc it would've been even worse to use RGB and RGBA simultaneously, bc then 0xFF00 could either be green or blue with 0 opacity.)

    Seems that Graphics.ColorType should've been a class which includes information about the color format - to preserve backwards compatibility, it could also be a Number (in which case it would be interpreted as RGB or -1 / COLOR_TRANSPARENT). Ofc that could've potentially led to performance issues (even worse than making it a Long).