Skip to content

Commit 18de7ad

Browse files
authored
fix: compatibility with chrome 51 (#454)
- added alternative to roundRect it not supported - added fallback if createImageBitmap(image, options) signature is not supported - added WebGlContext error message
2 parents 857c8e9 + ce7e730 commit 18de7ad

File tree

7 files changed

+144
-19
lines changed

7 files changed

+144
-19
lines changed

BROWSERS.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ Add the following to your \`vite.config.js\`:
5656
import legacy from '@vitejs/plugin-legacy';
5757

5858
export default {
59-
plugins: [
60-
legacy({
61-
targets: ['chrome>=38'],
62-
modernPolyfills: true,
63-
additionalLegacyPolyfills: ['whatwg-fetch'],
64-
}),
65-
],
59+
plugins: [
60+
legacy({
61+
targets: ['chrome>=38'],
62+
modernPolyfills: true,
63+
additionalLegacyPolyfills: ['whatwg-fetch'],
64+
}),
65+
],
6666
};
6767
```
6868

src/core/lib/WebGlContextWrapper.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ export class WebGlContextWrapper {
8484
public readonly LINK_STATUS;
8585
public readonly DYNAMIC_DRAW;
8686
public readonly COLOR_ATTACHMENT0;
87+
public readonly INVALID_ENUM: number;
88+
public readonly INVALID_OPERATION: number;
8789
//#endregion WebGL Enums
8890

8991
constructor(private gl: WebGLRenderingContext | WebGL2RenderingContext) {
@@ -175,6 +177,8 @@ export class WebGlContextWrapper {
175177
this.LINK_STATUS = gl.LINK_STATUS;
176178
this.DYNAMIC_DRAW = gl.DYNAMIC_DRAW;
177179
this.COLOR_ATTACHMENT0 = gl.COLOR_ATTACHMENT0;
180+
this.INVALID_ENUM = gl.INVALID_ENUM;
181+
this.INVALID_OPERATION = gl.INVALID_OPERATION;
178182
}
179183
/**
180184
* Returns true if the WebGL context is WebGL2
@@ -1020,6 +1024,18 @@ export class WebGlContextWrapper {
10201024
return gl.getExtension(name);
10211025
}
10221026

1027+
/**
1028+
* ```
1029+
* gl.getError(type);
1030+
* ```
1031+
*
1032+
* @returns
1033+
*/
1034+
getError() {
1035+
const { gl } = this;
1036+
return gl.getError();
1037+
}
1038+
10231039
/**
10241040
* ```
10251041
* gl.createVertexArray();

src/core/renderers/canvas/CanvasCoreRenderer.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ import {
3030
type QuadOptions,
3131
} from '../CoreRenderer.js';
3232
import { CanvasCoreTexture } from './CanvasCoreTexture.js';
33-
import { getBorder, getRadius, strokeLine } from './internal/C2DShaderUtils.js';
33+
import {
34+
getBorder,
35+
getRadius,
36+
roundRect,
37+
strokeLine,
38+
} from './internal/C2DShaderUtils.js';
3439
import {
3540
formatRgba,
3641
parseColorRgba,
@@ -166,7 +171,7 @@ export class CanvasCoreRenderer extends CoreRenderer {
166171

167172
if (radius) {
168173
const path = new Path2D();
169-
path.roundRect(tx, ty, width, height, radius);
174+
roundRect.call(path, tx, ty, width, height, radius);
170175
ctx.clip(path);
171176
}
172177

@@ -224,7 +229,8 @@ export class CanvasCoreRenderer extends CoreRenderer {
224229
ctx.strokeStyle = borderColor;
225230
ctx.globalAlpha = alpha;
226231
if (radius) {
227-
ctx.roundRect(
232+
roundRect.call(
233+
ctx,
228234
tx + borderInnerWidth,
229235
ty + borderInnerWidth,
230236
width - borderWidth,

src/core/renderers/canvas/internal/C2DShaderUtils.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,99 @@ export function getBorder(
8484
return undefined;
8585
}
8686

87+
export function roundRect(
88+
this: CanvasRenderingContext2D | Path2D,
89+
x: number,
90+
y: number,
91+
width: number,
92+
height: number,
93+
radius: number | DOMPointInit | (number | DOMPointInit)[],
94+
) {
95+
const context = Object.getPrototypeOf(this) as Path2D;
96+
if (!context.roundRect) {
97+
const fixOverlappingCorners = (radii: {
98+
topLeft: number;
99+
topRight: number;
100+
bottomRight: number;
101+
bottomLeft: number;
102+
}) => {
103+
const maxRadius = Math.min(width / 2, height / 2);
104+
const totalHorizontal =
105+
radii.topLeft + radii.topRight + radii.bottomRight + radii.bottomLeft;
106+
107+
if (totalHorizontal > width || totalHorizontal > height) {
108+
const scale =
109+
maxRadius /
110+
Math.max(
111+
radii.topLeft,
112+
radii.topRight,
113+
radii.bottomRight,
114+
radii.bottomLeft,
115+
);
116+
radii.topLeft *= scale;
117+
radii.topRight *= scale;
118+
radii.bottomRight *= scale;
119+
radii.bottomLeft *= scale;
120+
}
121+
};
122+
const radii =
123+
typeof radius === 'number'
124+
? {
125+
topLeft: radius,
126+
topRight: radius,
127+
bottomRight: radius,
128+
bottomLeft: radius,
129+
}
130+
: { topLeft: 0, topRight: 0, bottomRight: 0, bottomLeft: 0, ...radius };
131+
132+
fixOverlappingCorners(radii);
133+
134+
this.moveTo(x + radii.topLeft, y);
135+
this.lineTo(x + width - radii.topRight, y);
136+
this.ellipse(
137+
x + width - radii.topRight,
138+
y + radii.topRight,
139+
radii.topRight,
140+
radii.topRight,
141+
0,
142+
1.5 * Math.PI,
143+
2 * Math.PI,
144+
);
145+
this.lineTo(x + width, y + height - radii.bottomRight);
146+
this.ellipse(
147+
x + width - radii.bottomRight,
148+
y + height - radii.bottomRight,
149+
radii.bottomRight,
150+
radii.bottomRight,
151+
0,
152+
0,
153+
0.5 * Math.PI,
154+
);
155+
this.lineTo(x + radii.bottomLeft, y + height);
156+
this.ellipse(
157+
x + radii.bottomLeft,
158+
y + height - radii.bottomLeft,
159+
radii.bottomLeft,
160+
radii.bottomLeft,
161+
0,
162+
0.5 * Math.PI,
163+
Math.PI,
164+
);
165+
this.lineTo(x, y + radii.topLeft);
166+
this.ellipse(
167+
x + radii.topLeft,
168+
y + radii.topLeft,
169+
radii.topLeft,
170+
radii.topLeft,
171+
0,
172+
Math.PI,
173+
1.5 * Math.PI,
174+
);
175+
} else {
176+
this.roundRect(x, y, width, height, radius);
177+
}
178+
}
179+
87180
export function strokeLine(
88181
ctx: CanvasRenderingContext2D,
89182
x: number,

src/core/renderers/webgl/WebGlCoreShader.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,15 @@ export abstract class WebGlCoreShader extends CoreShader {
142142
glw.FRAGMENT_SHADER,
143143
fragmentSource,
144144
);
145+
145146
if (!vertexShader || !fragmentShader) {
146147
throw new Error(
147-
`Unable to create shader type: ${glw.FRAGMENT_SHADER}. Source: ${fragmentSource}`,
148+
`Unable to create the following shader(s): ${[
149+
!vertexShader && 'VERTEX_SHADER',
150+
!fragmentShader && 'FRAGMENT_SHADER',
151+
]
152+
.filter(Boolean)
153+
.join(' and ')}`,
148154
);
149155
}
150156

src/core/renderers/webgl/internal/ShaderUtils.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,22 @@ export function createShader(
100100
) {
101101
const shader = glw.createShader(type);
102102
if (!shader) {
103-
throw new Error(`Unable to create shader type: ${type}. Source: ${source}`);
103+
const glError = glw.getError();
104+
throw new Error(
105+
`Unable to create the shader: ${
106+
type === glw.VERTEX_SHADER ? 'VERTEX_SHADER' : 'FRAGMENT_SHADER'
107+
}.${glError ? ` WebGlContext Error: ${glError}` : ''}`,
108+
);
104109
}
110+
105111
glw.shaderSource(shader, source);
106112
glw.compileShader(shader);
107113
const success = !!glw.getShaderParameter(shader, glw.COMPILE_STATUS);
108114
if (success) {
109115
return shader;
110116
}
111117

112-
console.log(glw.getShaderInfoLog(shader));
118+
console.error(glw.getShaderInfoLog(shader));
113119
glw.deleteShader(shader);
114120
}
115121

@@ -131,7 +137,7 @@ export function createProgram(
131137
return program;
132138
}
133139

134-
console.log(glw.getProgramInfoLog(program));
140+
console.warn(glw.getProgramInfoLog(program));
135141
glw.deleteProgram(program);
136142
return undefined;
137143
}

visual-regression/src/snapshot.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ export async function saveFailedSnapshot(
149149
writeTasks.push(
150150
fs.promises.writeFile(
151151
path.join(failedResultsDir, `${subtestName}-${snapshotIndex}-diff.png`),
152-
152+
153153
PNG.sync.write(diffPng),
154154
),
155155
);
@@ -171,7 +171,6 @@ export function compareBuffers(
171171
width: number,
172172
height: number,
173173
): CompareResult {
174-
175174
const diff = new PNG({ width: width as number, height: height as number });
176175
const actualImage = PNG.sync.read(actualImageBuffer);
177176
const expectedImage = PNG.sync.read(expectedImageBuffer);
@@ -187,11 +186,10 @@ export function compareBuffers(
187186
};
188187
}
189188

190-
191189
const count = pixelmatch(
192190
actualImage.data,
193191
expectedImage.data,
194-
192+
195193
diff.data,
196194
width,
197195
height,
@@ -202,7 +200,7 @@ export function compareBuffers(
202200

203201
return {
204202
doesMatch,
205-
203+
206204
diffImageBuffer: doesMatch ? undefined : diff,
207205
reason: doesMatch ? undefined : `${count} pixels differ`,
208206
};

0 commit comments

Comments
 (0)