Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions BROWSERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ Add the following to your \`vite.config.js\`:
import legacy from '@vitejs/plugin-legacy';

export default {
plugins: [
legacy({
targets: ['chrome>=38'],
modernPolyfills: true,
additionalLegacyPolyfills: ['whatwg-fetch'],
}),
],
plugins: [
legacy({
targets: ['chrome>=38'],
modernPolyfills: true,
additionalLegacyPolyfills: ['whatwg-fetch'],
}),
],
};
```

Expand Down
16 changes: 16 additions & 0 deletions src/core/lib/WebGlContextWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ export class WebGlContextWrapper {
public readonly LINK_STATUS;
public readonly DYNAMIC_DRAW;
public readonly COLOR_ATTACHMENT0;
public readonly INVALID_ENUM: number;
public readonly INVALID_OPERATION: number;
//#endregion WebGL Enums

constructor(private gl: WebGLRenderingContext | WebGL2RenderingContext) {
Expand Down Expand Up @@ -175,6 +177,8 @@ export class WebGlContextWrapper {
this.LINK_STATUS = gl.LINK_STATUS;
this.DYNAMIC_DRAW = gl.DYNAMIC_DRAW;
this.COLOR_ATTACHMENT0 = gl.COLOR_ATTACHMENT0;
this.INVALID_ENUM = gl.INVALID_ENUM;
this.INVALID_OPERATION = gl.INVALID_OPERATION;
}
/**
* Returns true if the WebGL context is WebGL2
Expand Down Expand Up @@ -1020,6 +1024,18 @@ export class WebGlContextWrapper {
return gl.getExtension(name);
}

/**
* ```
* gl.getError(type);
* ```
*
* @returns
*/
getError() {
const { gl } = this;
return gl.getError();
}

/**
* ```
* gl.createVertexArray();
Expand Down
12 changes: 9 additions & 3 deletions src/core/renderers/canvas/CanvasCoreRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ import {
type QuadOptions,
} from '../CoreRenderer.js';
import { CanvasCoreTexture } from './CanvasCoreTexture.js';
import { getBorder, getRadius, strokeLine } from './internal/C2DShaderUtils.js';
import {
getBorder,
getRadius,
roundRect,
strokeLine,
} from './internal/C2DShaderUtils.js';
import {
formatRgba,
parseColorRgba,
Expand Down Expand Up @@ -166,7 +171,7 @@ export class CanvasCoreRenderer extends CoreRenderer {

if (radius) {
const path = new Path2D();
path.roundRect(tx, ty, width, height, radius);
roundRect.call(path, tx, ty, width, height, radius);
ctx.clip(path);
}

Expand Down Expand Up @@ -224,7 +229,8 @@ export class CanvasCoreRenderer extends CoreRenderer {
ctx.strokeStyle = borderColor;
ctx.globalAlpha = alpha;
if (radius) {
ctx.roundRect(
roundRect.call(
ctx,
tx + borderInnerWidth,
ty + borderInnerWidth,
width - borderWidth,
Expand Down
93 changes: 93 additions & 0 deletions src/core/renderers/canvas/internal/C2DShaderUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,99 @@ export function getBorder(
return undefined;
}

export function roundRect(
this: CanvasRenderingContext2D | Path2D,
x: number,
y: number,
width: number,
height: number,
radius: number | DOMPointInit | (number | DOMPointInit)[],
) {
const context = Object.getPrototypeOf(this) as Path2D;
if (!context.roundRect) {
const fixOverlappingCorners = (radii: {
topLeft: number;
topRight: number;
bottomRight: number;
bottomLeft: number;
}) => {
const maxRadius = Math.min(width / 2, height / 2);
const totalHorizontal =
radii.topLeft + radii.topRight + radii.bottomRight + radii.bottomLeft;

if (totalHorizontal > width || totalHorizontal > height) {
const scale =
maxRadius /
Math.max(
radii.topLeft,
radii.topRight,
radii.bottomRight,
radii.bottomLeft,
);
radii.topLeft *= scale;
radii.topRight *= scale;
radii.bottomRight *= scale;
radii.bottomLeft *= scale;
}
};
const radii =
typeof radius === 'number'
? {
topLeft: radius,
topRight: radius,
bottomRight: radius,
bottomLeft: radius,
}
: { topLeft: 0, topRight: 0, bottomRight: 0, bottomLeft: 0, ...radius };

fixOverlappingCorners(radii);

this.moveTo(x + radii.topLeft, y);
this.lineTo(x + width - radii.topRight, y);
this.ellipse(
x + width - radii.topRight,
y + radii.topRight,
radii.topRight,
radii.topRight,
0,
1.5 * Math.PI,
2 * Math.PI,
);
this.lineTo(x + width, y + height - radii.bottomRight);
this.ellipse(
x + width - radii.bottomRight,
y + height - radii.bottomRight,
radii.bottomRight,
radii.bottomRight,
0,
0,
0.5 * Math.PI,
);
this.lineTo(x + radii.bottomLeft, y + height);
this.ellipse(
x + radii.bottomLeft,
y + height - radii.bottomLeft,
radii.bottomLeft,
radii.bottomLeft,
0,
0.5 * Math.PI,
Math.PI,
);
this.lineTo(x, y + radii.topLeft);
this.ellipse(
x + radii.topLeft,
y + radii.topLeft,
radii.topLeft,
radii.topLeft,
0,
Math.PI,
1.5 * Math.PI,
);
} else {
this.roundRect(x, y, width, height, radius);
}
}

export function strokeLine(
ctx: CanvasRenderingContext2D,
x: number,
Expand Down
8 changes: 7 additions & 1 deletion src/core/renderers/webgl/WebGlCoreShader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,15 @@ export abstract class WebGlCoreShader extends CoreShader {
glw.FRAGMENT_SHADER,
fragmentSource,
);

if (!vertexShader || !fragmentShader) {
throw new Error(
`Unable to create shader type: ${glw.FRAGMENT_SHADER}. Source: ${fragmentSource}`,
`Unable to create the following shader(s): ${[
!vertexShader && 'VERTEX_SHADER',
!fragmentShader && 'FRAGMENT_SHADER',
]
.filter(Boolean)
.join(' and ')}`,
);
}

Expand Down
12 changes: 9 additions & 3 deletions src/core/renderers/webgl/internal/ShaderUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,22 @@ export function createShader(
) {
const shader = glw.createShader(type);
if (!shader) {
throw new Error(`Unable to create shader type: ${type}. Source: ${source}`);
const glError = glw.getError();
throw new Error(
`Unable to create the shader: ${
type === glw.VERTEX_SHADER ? 'VERTEX_SHADER' : 'FRAGMENT_SHADER'
}.${glError ? ` WebGlContext Error: ${glError}` : ''}`,
);
}

glw.shaderSource(shader, source);
glw.compileShader(shader);
const success = !!glw.getShaderParameter(shader, glw.COMPILE_STATUS);
if (success) {
return shader;
}

console.log(glw.getShaderInfoLog(shader));
console.error(glw.getShaderInfoLog(shader));
glw.deleteShader(shader);
}

Expand All @@ -131,7 +137,7 @@ export function createProgram(
return program;
}

console.log(glw.getProgramInfoLog(program));
console.warn(glw.getProgramInfoLog(program));
glw.deleteProgram(program);
return undefined;
}
8 changes: 3 additions & 5 deletions visual-regression/src/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export async function saveFailedSnapshot(
writeTasks.push(
fs.promises.writeFile(
path.join(failedResultsDir, `${subtestName}-${snapshotIndex}-diff.png`),

PNG.sync.write(diffPng),
),
);
Expand All @@ -171,7 +171,6 @@ export function compareBuffers(
width: number,
height: number,
): CompareResult {

const diff = new PNG({ width: width as number, height: height as number });
const actualImage = PNG.sync.read(actualImageBuffer);
const expectedImage = PNG.sync.read(expectedImageBuffer);
Expand All @@ -187,11 +186,10 @@ export function compareBuffers(
};
}


const count = pixelmatch(
actualImage.data,
expectedImage.data,

diff.data,
width,
height,
Expand All @@ -202,7 +200,7 @@ export function compareBuffers(

return {
doesMatch,

diffImageBuffer: doesMatch ? undefined : diff,
reason: doesMatch ? undefined : `${count} pixels differ`,
};
Expand Down