react-x11 2.32.0 → 2.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/Reconciler.js +5 -0
- package/src/a11y.js +4 -0
- package/src/appcontext.js +16 -1
- package/src/cocoa/app.js +54 -1
- package/src/cocoa/fonts.js +30 -6
- package/src/cocoa/player.js +177 -0
- package/src/cocoa/promotion.js +4 -0
- package/src/cocoa/sprites.js +188 -34
- package/src/cocoa/video.js +122 -0
- package/src/host.js +1 -0
- package/src/index.d.ts +14 -1
- package/src/index.js +7 -0
- package/src/mediaplayback.js +37 -0
- package/src/node.d.ts +25 -2
- package/src/nodes/fit.js +46 -0
- package/src/nodes/image.js +37 -6
- package/src/nodes/kinds.js +1 -0
- package/src/nodes/layouthost.js +1 -0
- package/src/nodes/video.js +641 -0
- package/src/styles.js +19 -4
- package/src/types/elements.d.ts +54 -0
- package/src/types/nodes.d.ts +19 -0
- package/src/types/style.d.ts +11 -0
- package/src/types/video.d.ts +123 -0
- package/src/videoframes.js +375 -0
- package/src/videohooks.js +29 -0
package/src/nodes/fit.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// `objectFit`: where a picture with a size of its own goes in a box that has
|
|
2
|
+
// another — CSS's `object-fit`, for `<image>` and `<video>`, centred the way
|
|
3
|
+
// CSS's default `object-position: 50% 50%` centres it. A leaf: no node, no
|
|
4
|
+
// backend, rects in and a rect out.
|
|
5
|
+
|
|
6
|
+
export const OBJECT_FITS = Object.freeze([
|
|
7
|
+
'fill',
|
|
8
|
+
'contain',
|
|
9
|
+
'cover',
|
|
10
|
+
'none',
|
|
11
|
+
'scale-down',
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
/** The element's `objectFit`, or its default where the style names none. */
|
|
15
|
+
export function objectFitOf(style, fallback) {
|
|
16
|
+
const fit = style?.objectFit;
|
|
17
|
+
return OBJECT_FITS.includes(fit) ? fit : fallback;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Where a `width` x `height` picture goes in `box` under `fit`: `fill`
|
|
22
|
+
* stretches it to the box, `contain` scales it to fit inside with bars,
|
|
23
|
+
* `cover` scales it to fill with the overflow cut (by the caller), `none`
|
|
24
|
+
* leaves it its own size, and `scale-down` is `none` or `contain`, whichever
|
|
25
|
+
* is smaller. Its edges are snapped to whole pixels, so a picture drawn
|
|
26
|
+
* there and a layer placed there cover exactly the same ones — except under
|
|
27
|
+
* `fill`, which is the box itself, as an `<image>` has always been drawn.
|
|
28
|
+
*/
|
|
29
|
+
export function fitRect(box, width, height, fit) {
|
|
30
|
+
if (fit === 'fill' || !(width > 0 && height > 0)) return { ...box };
|
|
31
|
+
let k;
|
|
32
|
+
if (fit === 'none') k = 1;
|
|
33
|
+
else {
|
|
34
|
+
const sx = box.width / width;
|
|
35
|
+
const sy = box.height / height;
|
|
36
|
+
k = fit === 'cover' ? Math.max(sx, sy) : Math.min(sx, sy);
|
|
37
|
+
if (fit === 'scale-down') k = Math.min(k, 1);
|
|
38
|
+
}
|
|
39
|
+
const w = width * k;
|
|
40
|
+
const h = height * k;
|
|
41
|
+
const x0 = Math.round(box.x + (box.width - w) / 2);
|
|
42
|
+
const y0 = Math.round(box.y + (box.height - h) / 2);
|
|
43
|
+
const x1 = Math.round(box.x + (box.width + w) / 2);
|
|
44
|
+
const y1 = Math.round(box.y + (box.height + h) / 2);
|
|
45
|
+
return { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
46
|
+
}
|
package/src/nodes/image.js
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from '../imagesource.js';
|
|
19
19
|
import { loadImageFile } from '../imagedecode.js';
|
|
20
20
|
import { symbolWeight, symbolsFor, warnOnce } from '../symbols.js';
|
|
21
|
+
import { fitRect, objectFitOf } from './fit.js';
|
|
21
22
|
import { intrinsicSize } from './layout.js';
|
|
22
23
|
import { Node } from './node.js';
|
|
23
24
|
import { DEV } from './util.js';
|
|
@@ -317,12 +318,42 @@ export class ImageNode extends Node {
|
|
|
317
318
|
}
|
|
318
319
|
if (!this.image) return;
|
|
319
320
|
const content = this.contentBox();
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
321
|
+
const fit = objectFitOf(this.style, 'fill');
|
|
322
|
+
if (fit === 'fill') {
|
|
323
|
+
ctx.drawImage(
|
|
324
|
+
this.image,
|
|
325
|
+
content.x,
|
|
326
|
+
content.y,
|
|
327
|
+
content.width,
|
|
328
|
+
content.height,
|
|
329
|
+
);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
// the source's size in device pixels, as `measureContent` takes it
|
|
333
|
+
const s = this.scale;
|
|
334
|
+
const rect = fitRect(
|
|
335
|
+
content,
|
|
336
|
+
(this.image.width ?? 0) * s,
|
|
337
|
+
(this.image.height ?? 0) * s,
|
|
338
|
+
fit,
|
|
326
339
|
);
|
|
340
|
+
if (!(rect.width > 0 && rect.height > 0)) return;
|
|
341
|
+
const inside =
|
|
342
|
+
rect.x >= content.x &&
|
|
343
|
+
rect.y >= content.y &&
|
|
344
|
+
rect.x + rect.width <= content.x + content.width &&
|
|
345
|
+
rect.y + rect.height <= content.y + content.height;
|
|
346
|
+
if (!inside) {
|
|
347
|
+
// `cover`, and `none` larger than the box: cut to the content box
|
|
348
|
+
ctx.save();
|
|
349
|
+
ctx.beginPath();
|
|
350
|
+
ctx.rect(content.x, content.y, content.width, content.height);
|
|
351
|
+
ctx.clip();
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
ctx.drawImage(this.image, rect.x, rect.y, rect.width, rect.height);
|
|
355
|
+
} finally {
|
|
356
|
+
if (!inside) ctx.restore();
|
|
357
|
+
}
|
|
327
358
|
}
|
|
328
359
|
}
|
package/src/nodes/kinds.js
CHANGED