Skip to content

Make CanvasRenderer treat clearColor as RGBA, like WebGlRenderer - #869

Open
guilhermesimoes wants to merge 5 commits into
lightning-js:mainfrom
guilhermesimoes:feat/canvas-standard-setClearColor
Open

Make CanvasRenderer treat clearColor as RGBA, like WebGlRenderer#869
guilhermesimoes wants to merge 5 commits into
lightning-js:mainfrom
guilhermesimoes:feat/canvas-standard-setClearColor

Conversation

@guilhermesimoes

Copy link
Copy Markdown
Contributor

Currently if we do stage.setClearColor(0x000000FF) in WebGL the background is black, but in Canvas it's white (because it thinks we're using ARGB instead of RGBA). Let's change this so that both WebGL and Canvas are consistent. And also so that app.props.color = 0x000000FF is consistent with app.stage.setClearColor(0x000000FF).

Comment thread src/core/lib/colorCache.ts Outdated
const parsedRgbaColors: Map<number, string> = new Map();

export function normalizeCanvasColor(color: number, isRGBA: boolean = false) {
export function normalizeCanvasColor(color: number, isRGBA: boolean = true) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you agree with the second commit that inverts this default.
If you don't agree I can undo this change.

@guilhermesimoes guilhermesimoes Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, I also thought about splitting this function into two: normalizeCanvasColor and normalizeCanvasColorArgb. I generally subscribe to the idea of avoiding boolean params in functions. Tell me what you think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm much more in favor of splitting it in two sep functions! Since it already gets the value from 2 distinct caches and two distinct parseTo<variant>String functions, it would be cheaper to make 2 explicit functions for this.

I would also immediately inline the parseToRgbaString / parsedArgbColors functions to avoid the additional function hop. And remove them from utils, no one else but this function seems to be using them.

Great suggestion and love the article!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I split the functions into two.

The utils parseTo<variant>String would actually be useful to us if they were exported. I noticed we have our own implementations of these.

@guilhermesimoes
guilhermesimoes force-pushed the feat/canvas-standard-setClearColor branch from 3fc42a6 to d97e768 Compare August 31, 2026 09:18
Comment thread src/core/lib/colorCache.ts Outdated
const parsedRgbaColors: Map<number, string> = new Map();

export function normalizeCanvasColor(color: number, isRGBA: boolean = false) {
export function normalizeCanvasColor(color: number, isRGBA: boolean = true) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm much more in favor of splitting it in two sep functions! Since it already gets the value from 2 distinct caches and two distinct parseTo<variant>String functions, it would be cheaper to make 2 explicit functions for this.

I would also immediately inline the parseToRgbaString / parsedArgbColors functions to avoid the additional function hop. And remove them from utils, no one else but this function seems to be using them.

Great suggestion and love the article!

Applying & 0xff twice is a no-op. The second mask does nothing since the
value is already clamped to 8 bits.
Destructuring creates an intermediate object scope, avoid it.
Comment thread src/core/lib/colorParser.ts
Comment on lines -52 to -54
const b = (abgr >>> 16) & 0xff & 0xff;
const g = (abgr >>> 8) & 0xff & 0xff;
const r = abgr & 0xff & 0xff;

@guilhermesimoes guilhermesimoes Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this code correct?
The variable is named abgr and the variables are a, b, g, r.
Shouldn't it be argb and the variables be a, r, g, b?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the variable is probably off - but the logic below works, its just the declaration of the incoming number.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You sure it's correct? Shouldn't the r and the b be swapped? Like so

const a = ((argb >>> 24) & 0xff) / 255;
const r = (argb >>> 16) & 0xff;
const g = (argb >>> 8) & 0xff;
const b = argb & 0xff;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah for making it look better, for sure!

Comment on lines -52 to -54
const b = (abgr >>> 16) & 0xff & 0xff;
const g = (abgr >>> 8) & 0xff & 0xff;
const r = abgr & 0xff & 0xff;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the variable is probably off - but the logic below works, its just the declaration of the incoming number.

Comment thread src/core/lib/colorParser.ts
}
targetCache.set(color, out);

out = parseToAbgrString(argbColor);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nit picky thing - instead of calling parseToAbgrString here

can you just inline/copy the entire contents of the function here? no need to do the function call hop and object creation when this is the only place that uses the function.

out = parseToRgbaString(color);
} else {
out = parseToAbgrString(color);
out = parseToRgbaString(rgbaColor);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nit picky thing - instead of calling parseToRgbaString here

can you just inline/copy the entire contents of the function here? no need to do the function call hop and object creation when this is the only place that uses the function.

return { isWhite: false, a, r, g, b };
}

export function parseToAbgrString(abgr: number): string {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should remove this from colorParser.ts and inline in the above function.

return `rgba(${r},${g},${b},${a})`;
}

export function parseToRgbaString(rgba: number): string {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, just remove this entire function and inline it above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants