@solidtv/renderer 1.0.0 → 1.0.2
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/dist/src/core/CoreNode.js +13 -11
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreTextNode.js +2 -1
- package/dist/src/core/CoreTextNode.js.map +1 -1
- package/dist/src/core/lib/utils.d.ts +2 -2
- package/dist/src/core/lib/utils.js +21 -21
- package/dist/src/core/lib/utils.js.map +1 -1
- package/dist/src/core/renderers/CoreRenderer.d.ts +0 -30
- package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +2 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.js +128 -47
- package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasShaderNode.d.ts +1 -2
- package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -1
- package/dist/src/core/renderers/webgl/SdfRenderOp.d.ts +5 -5
- package/dist/src/core/renderers/webgl/SdfRenderOp.js +8 -8
- package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +3 -4
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
- package/dist/src/core/shaders/canvas/Border.js +8 -11
- package/dist/src/core/shaders/canvas/Border.js.map +1 -1
- package/dist/src/core/shaders/canvas/HolePunch.js +2 -1
- package/dist/src/core/shaders/canvas/HolePunch.js.map +1 -1
- package/dist/src/core/shaders/canvas/LinearGradient.js +23 -4
- package/dist/src/core/shaders/canvas/LinearGradient.js.map +1 -1
- package/dist/src/core/shaders/canvas/RadialGradient.js +7 -5
- package/dist/src/core/shaders/canvas/RadialGradient.js.map +1 -1
- package/dist/src/core/shaders/canvas/Rounded.js +2 -2
- package/dist/src/core/shaders/canvas/Rounded.js.map +1 -1
- package/dist/src/core/shaders/canvas/RoundedWithBorder.js +2 -2
- package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +1 -1
- package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +5 -4
- package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +1 -1
- package/dist/src/core/shaders/canvas/RoundedWithShadow.js +5 -4
- package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -1
- package/dist/src/core/shaders/canvas/Shadow.js +4 -2
- package/dist/src/core/shaders/canvas/Shadow.js.map +1 -1
- package/dist/src/core/shaders/canvas/utils/render.js +0 -15
- package/dist/src/core/shaders/canvas/utils/render.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/core/CoreNode.test.ts +2 -2
- package/src/core/CoreNode.ts +13 -11
- package/src/core/CoreTextNode.ts +3 -1
- package/src/core/lib/utils.ts +23 -25
- package/src/core/renderers/CoreRenderer.ts +0 -31
- package/src/core/renderers/canvas/CanvasRenderer.ts +158 -63
- package/src/core/renderers/canvas/CanvasShaderNode.ts +1 -2
- package/src/core/renderers/webgl/SdfRenderOp.ts +7 -7
- package/src/core/renderers/webgl/WebGlShaderProgram.ts +3 -6
- package/src/core/shaders/canvas/Border.ts +11 -15
- package/src/core/shaders/canvas/HolePunch.ts +2 -1
- package/src/core/shaders/canvas/LinearGradient.ts +26 -7
- package/src/core/shaders/canvas/RadialGradient.ts +7 -10
- package/src/core/shaders/canvas/Rounded.ts +5 -5
- package/src/core/shaders/canvas/RoundedWithBorder.ts +5 -5
- package/src/core/shaders/canvas/RoundedWithBorderAndShadow.ts +9 -8
- package/src/core/shaders/canvas/RoundedWithShadow.ts +6 -5
- package/src/core/shaders/canvas/Shadow.ts +7 -5
- package/src/core/shaders/canvas/utils/render.ts +0 -18
package/src/core/lib/utils.ts
CHANGED
|
@@ -63,8 +63,8 @@ export function getRgbaString(color: RGBA) {
|
|
|
63
63
|
export interface Rect {
|
|
64
64
|
x: number;
|
|
65
65
|
y: number;
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
w: number;
|
|
67
|
+
h: number;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
export interface RectWithValid extends Rect {
|
|
@@ -140,15 +140,15 @@ export function convertBoundToRect(bound: Bound, out?: Rect): Rect {
|
|
|
140
140
|
if (out) {
|
|
141
141
|
out.x = bound.x1;
|
|
142
142
|
out.y = bound.y1;
|
|
143
|
-
out.
|
|
144
|
-
out.
|
|
143
|
+
out.w = bound.x2 - bound.x1;
|
|
144
|
+
out.h = bound.y2 - bound.y1;
|
|
145
145
|
return out;
|
|
146
146
|
}
|
|
147
147
|
return {
|
|
148
148
|
x: bound.x1,
|
|
149
149
|
y: bound.y1,
|
|
150
|
-
|
|
151
|
-
|
|
150
|
+
w: bound.x2 - bound.x1,
|
|
151
|
+
h: bound.y2 - bound.y1,
|
|
152
152
|
};
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -161,35 +161,35 @@ export function intersectRect<T extends Rect = Rect>(
|
|
|
161
161
|
export function intersectRect(a: Rect, b: Rect, out?: Rect): Rect {
|
|
162
162
|
const x = Math.max(a.x, b.x);
|
|
163
163
|
const y = Math.max(a.y, b.y);
|
|
164
|
-
const
|
|
165
|
-
const
|
|
166
|
-
if (
|
|
164
|
+
const w = Math.min(a.x + a.w, b.x + b.w) - x;
|
|
165
|
+
const h = Math.min(a.y + a.h, b.y + b.h) - y;
|
|
166
|
+
if (w > 0 && h > 0) {
|
|
167
167
|
if (out) {
|
|
168
168
|
out.x = x;
|
|
169
169
|
out.y = y;
|
|
170
|
-
out.
|
|
171
|
-
out.
|
|
170
|
+
out.w = w;
|
|
171
|
+
out.h = h;
|
|
172
172
|
return out;
|
|
173
173
|
}
|
|
174
174
|
return {
|
|
175
175
|
x,
|
|
176
176
|
y,
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
w,
|
|
178
|
+
h,
|
|
179
179
|
};
|
|
180
180
|
}
|
|
181
181
|
if (out) {
|
|
182
182
|
out.x = 0;
|
|
183
183
|
out.y = 0;
|
|
184
|
-
out.
|
|
185
|
-
out.
|
|
184
|
+
out.w = 0;
|
|
185
|
+
out.h = 0;
|
|
186
186
|
return out;
|
|
187
187
|
}
|
|
188
188
|
return {
|
|
189
189
|
x: 0,
|
|
190
190
|
y: 0,
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
w: 0,
|
|
192
|
+
h: 0,
|
|
193
193
|
};
|
|
194
194
|
}
|
|
195
195
|
|
|
@@ -199,15 +199,15 @@ export function copyRect(a: Rect, out?: Rect): Rect {
|
|
|
199
199
|
if (out) {
|
|
200
200
|
out.x = a.x;
|
|
201
201
|
out.y = a.y;
|
|
202
|
-
out.
|
|
203
|
-
out.
|
|
202
|
+
out.w = a.w;
|
|
203
|
+
out.h = a.h;
|
|
204
204
|
return out;
|
|
205
205
|
}
|
|
206
206
|
return {
|
|
207
207
|
x: a.x,
|
|
208
208
|
y: a.y,
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
w: a.w,
|
|
210
|
+
h: a.h,
|
|
211
211
|
};
|
|
212
212
|
}
|
|
213
213
|
|
|
@@ -218,9 +218,7 @@ export function compareRect(a: Rect | null, b: Rect | null): boolean {
|
|
|
218
218
|
if (a === null || b === null) {
|
|
219
219
|
return false;
|
|
220
220
|
}
|
|
221
|
-
return
|
|
222
|
-
a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height
|
|
223
|
-
);
|
|
221
|
+
return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
|
|
224
222
|
}
|
|
225
223
|
|
|
226
224
|
export function boundInsideBound(bound1: Bound, bound2: Bound) {
|
|
@@ -250,7 +248,7 @@ export function isBoundPositive(bound: Bound): boolean {
|
|
|
250
248
|
}
|
|
251
249
|
|
|
252
250
|
export function isRectPositive(rect: Rect): boolean {
|
|
253
|
-
return rect.
|
|
251
|
+
return rect.w > 0 && rect.h > 0;
|
|
254
252
|
}
|
|
255
253
|
|
|
256
254
|
/**
|
|
@@ -1,42 +1,11 @@
|
|
|
1
|
-
import type { Dimensions } from '../../common/CommonTypes.js';
|
|
2
1
|
import type { CoreNode } from '../CoreNode.js';
|
|
3
|
-
import type { TextureOptions } from '../CoreTextureManager.js';
|
|
4
2
|
import type { Stage } from '../Stage.js';
|
|
5
3
|
import type { ContextSpy } from '../lib/ContextSpy.js';
|
|
6
|
-
import type { RenderCoords } from '../lib/RenderCoords.js';
|
|
7
|
-
import type { RectWithValid } from '../lib/utils.js';
|
|
8
4
|
import type { CoreShaderProgram } from './CoreShaderProgram.js';
|
|
9
5
|
import type { Texture, TextureCoords } from '../textures/Texture.js';
|
|
10
6
|
import { CoreContextTexture } from './CoreContextTexture.js';
|
|
11
7
|
import type { CoreShaderType, CoreShaderNode } from './CoreShaderNode.js';
|
|
12
8
|
|
|
13
|
-
export interface QuadOptions {
|
|
14
|
-
width: number;
|
|
15
|
-
height: number;
|
|
16
|
-
colorTl: number;
|
|
17
|
-
colorTr: number;
|
|
18
|
-
colorBl: number;
|
|
19
|
-
colorBr: number;
|
|
20
|
-
texture: Texture | null;
|
|
21
|
-
textureOptions: TextureOptions | null;
|
|
22
|
-
textureCoords: TextureCoords | undefined;
|
|
23
|
-
zIndex: number;
|
|
24
|
-
shader: CoreShaderNode | null;
|
|
25
|
-
alpha: number;
|
|
26
|
-
clippingRect: RectWithValid;
|
|
27
|
-
tx: number;
|
|
28
|
-
ty: number;
|
|
29
|
-
ta: number;
|
|
30
|
-
tb: number;
|
|
31
|
-
tc: number;
|
|
32
|
-
td: number;
|
|
33
|
-
renderCoords?: RenderCoords;
|
|
34
|
-
rtt: boolean;
|
|
35
|
-
parentHasRenderTexture: boolean;
|
|
36
|
-
framebufferDimensions: Dimensions | null;
|
|
37
|
-
time?: number | null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
9
|
export interface CoreRendererOptions {
|
|
41
10
|
stage: Stage;
|
|
42
11
|
canvas: HTMLCanvasElement | OffscreenCanvas;
|
|
@@ -2,11 +2,7 @@ import type { CoreNode } from '../../CoreNode.js';
|
|
|
2
2
|
import { SubTexture } from '../../textures/SubTexture.js';
|
|
3
3
|
import { TextureType, type Texture } from '../../textures/Texture.js';
|
|
4
4
|
import type { CoreContextTexture } from '../CoreContextTexture.js';
|
|
5
|
-
import {
|
|
6
|
-
CoreRenderer,
|
|
7
|
-
type CoreRendererOptions,
|
|
8
|
-
type QuadOptions,
|
|
9
|
-
} from '../CoreRenderer.js';
|
|
5
|
+
import { CoreRenderer, type CoreRendererOptions } from '../CoreRenderer.js';
|
|
10
6
|
import { CanvasTexture } from './CanvasTexture.js';
|
|
11
7
|
import { parseColor } from '../../lib/colorParser.js';
|
|
12
8
|
import { CanvasShaderNode, type CanvasShaderType } from './CanvasShaderNode.js';
|
|
@@ -52,7 +48,7 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
52
48
|
const ctx = this.context;
|
|
53
49
|
const { tx, ty, ta, tb, tc, td } = node.globalTransform!;
|
|
54
50
|
const clippingRect = node.clippingRect;
|
|
55
|
-
let texture = node.
|
|
51
|
+
let texture = (node.props.texture || this.stage.defaultTexture) as Texture;
|
|
56
52
|
// The Canvas2D renderer only supports image textures, no textures are used for color blocks
|
|
57
53
|
if (texture !== null) {
|
|
58
54
|
const textureType = texture.type;
|
|
@@ -67,7 +63,7 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
67
63
|
}
|
|
68
64
|
|
|
69
65
|
const hasTransform = ta !== 1;
|
|
70
|
-
const hasClipping = clippingRect.
|
|
66
|
+
const hasClipping = clippingRect.w !== 0 && clippingRect.h !== 0;
|
|
71
67
|
const shader = node.props.shader;
|
|
72
68
|
const hasShader = shader !== null;
|
|
73
69
|
|
|
@@ -82,8 +78,8 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
82
78
|
|
|
83
79
|
if (hasClipping === true) {
|
|
84
80
|
const path = new Path2D();
|
|
85
|
-
const { x, y,
|
|
86
|
-
path.rect(x, y,
|
|
81
|
+
const { x, y, w, h } = clippingRect;
|
|
82
|
+
path.rect(x, y, w, h);
|
|
87
83
|
ctx.clip(path);
|
|
88
84
|
}
|
|
89
85
|
|
|
@@ -104,40 +100,13 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
104
100
|
|
|
105
101
|
if (hasShader === true) {
|
|
106
102
|
let renderContext: (() => void) | null = () => {
|
|
107
|
-
this.renderContext(node);
|
|
108
|
-
};
|
|
109
|
-
const quad: QuadOptions = {
|
|
110
|
-
width: node.props.w,
|
|
111
|
-
height: node.props.h,
|
|
112
|
-
colorTl: node.premultipliedColorTl,
|
|
113
|
-
colorTr: node.premultipliedColorTr,
|
|
114
|
-
colorBl: node.premultipliedColorBl,
|
|
115
|
-
colorBr: node.premultipliedColorBr,
|
|
116
|
-
texture: texture,
|
|
117
|
-
textureOptions: node.props.textureOptions,
|
|
118
|
-
textureCoords: node.renderTextureCoords,
|
|
119
|
-
zIndex: node.zIndex, // zIndex usage?
|
|
120
|
-
shader: shader,
|
|
121
|
-
alpha: node.worldAlpha,
|
|
122
|
-
clippingRect: clippingRect,
|
|
123
|
-
tx,
|
|
124
|
-
ty,
|
|
125
|
-
ta,
|
|
126
|
-
tb,
|
|
127
|
-
tc,
|
|
128
|
-
td,
|
|
129
|
-
renderCoords: node.renderCoords,
|
|
130
|
-
rtt: node.props.rtt,
|
|
131
|
-
parentHasRenderTexture: node.parentHasRenderTexture,
|
|
132
|
-
framebufferDimensions: node.parentHasRenderTexture
|
|
133
|
-
? node.parentFramebufferDimensions
|
|
134
|
-
: null,
|
|
103
|
+
this.renderContext(node, texture);
|
|
135
104
|
};
|
|
136
105
|
|
|
137
|
-
(shader as CanvasShaderNode).render(ctx,
|
|
106
|
+
(shader as CanvasShaderNode).render(ctx, node, renderContext);
|
|
138
107
|
renderContext = null;
|
|
139
108
|
} else {
|
|
140
|
-
this.renderContext(node);
|
|
109
|
+
this.renderContext(node, texture);
|
|
141
110
|
}
|
|
142
111
|
|
|
143
112
|
if (saveAndRestore) {
|
|
@@ -145,9 +114,8 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
145
114
|
}
|
|
146
115
|
}
|
|
147
116
|
|
|
148
|
-
renderContext(node: CoreNode) {
|
|
117
|
+
renderContext(node: CoreNode, texture: Texture) {
|
|
149
118
|
const color = node.premultipliedColorTl;
|
|
150
|
-
const texture = node.renderTexture!;
|
|
151
119
|
const textureType = texture.type;
|
|
152
120
|
const tx = node.globalTransform!.tx;
|
|
153
121
|
const ty = node.globalTransform!.ty;
|
|
@@ -156,30 +124,57 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
156
124
|
|
|
157
125
|
if (textureType !== TextureType.color) {
|
|
158
126
|
const tintColor = parseColor(color);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
127
|
+
let image: ImageBitmap | HTMLCanvasElement | HTMLImageElement;
|
|
128
|
+
|
|
129
|
+
if (textureType === TextureType.subTexture) {
|
|
130
|
+
image = (
|
|
131
|
+
(texture as SubTexture).parentTexture.ctxTexture as CanvasTexture
|
|
132
|
+
).getImage(tintColor);
|
|
133
|
+
} else {
|
|
134
|
+
image = (texture.ctxTexture as CanvasTexture).getImage(tintColor);
|
|
165
135
|
}
|
|
166
|
-
const image = (
|
|
167
|
-
(texture as SubTexture).parentTexture.ctxTexture as CanvasTexture
|
|
168
|
-
).getImage(tintColor);
|
|
169
|
-
const props = (texture as SubTexture).props;
|
|
170
136
|
|
|
171
137
|
this.context.globalAlpha = tintColor.a ?? node.worldAlpha;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
138
|
+
|
|
139
|
+
const txCoords = node.textureCoords;
|
|
140
|
+
if (txCoords) {
|
|
141
|
+
const ix = image.width;
|
|
142
|
+
const iy = image.height;
|
|
143
|
+
|
|
144
|
+
let sx = txCoords.x1 * ix;
|
|
145
|
+
let sy = txCoords.y1 * iy;
|
|
146
|
+
let sw = (txCoords.x2 - txCoords.x1) * ix;
|
|
147
|
+
let sh = (txCoords.y2 - txCoords.y1) * iy;
|
|
148
|
+
|
|
149
|
+
let flipX = false;
|
|
150
|
+
let flipY = false;
|
|
151
|
+
|
|
152
|
+
if (sw < 0) {
|
|
153
|
+
flipX = true;
|
|
154
|
+
sx += sw;
|
|
155
|
+
sw = Math.abs(sw);
|
|
156
|
+
}
|
|
157
|
+
if (sh < 0) {
|
|
158
|
+
flipY = true;
|
|
159
|
+
sy += sh;
|
|
160
|
+
sh = Math.abs(sh);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (flipX || flipY) {
|
|
164
|
+
this.context.save();
|
|
165
|
+
this.context.translate(
|
|
166
|
+
tx + (flipX ? width : 0),
|
|
167
|
+
ty + (flipY ? height : 0),
|
|
168
|
+
);
|
|
169
|
+
this.context.scale(flipX ? -1 : 1, flipY ? -1 : 1);
|
|
170
|
+
this.context.drawImage(image, sx, sy, sw, sh, 0, 0, width, height);
|
|
171
|
+
this.context.restore();
|
|
172
|
+
} else {
|
|
173
|
+
this.context.drawImage(image, sx, sy, sw, sh, tx, ty, width, height);
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
this.context.drawImage(image, tx, ty, width, height);
|
|
177
|
+
}
|
|
183
178
|
this.context.globalAlpha = 1;
|
|
184
179
|
return;
|
|
185
180
|
}
|
|
@@ -201,8 +196,22 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
201
196
|
endY = ty;
|
|
202
197
|
endColor = node.premultipliedColorTr;
|
|
203
198
|
}
|
|
199
|
+
|
|
200
|
+
let startColor = color;
|
|
201
|
+
const startAlpha = (startColor >>> 24) & 0xff;
|
|
202
|
+
const endAlpha = (endColor >>> 24) & 0xff;
|
|
203
|
+
|
|
204
|
+
// if one of the colors has 0 alpha, we want to match the RGB channels
|
|
205
|
+
// to the other color to prevent white bleed during zero alpha interpolation.
|
|
206
|
+
if (startAlpha === 0 && endAlpha > 0) {
|
|
207
|
+
startColor =
|
|
208
|
+
((startColor & 0xff000000) | (endColor & 0x00ffffff)) >>> 0;
|
|
209
|
+
} else if (endAlpha === 0 && startAlpha > 0) {
|
|
210
|
+
endColor = ((endColor & 0xff000000) | (startColor & 0x00ffffff)) >>> 0;
|
|
211
|
+
}
|
|
212
|
+
|
|
204
213
|
const gradient = this.context.createLinearGradient(tx, ty, endX, endY);
|
|
205
|
-
gradient.addColorStop(0, normalizeCanvasColor(
|
|
214
|
+
gradient.addColorStop(0, normalizeCanvasColor(startColor));
|
|
206
215
|
gradient.addColorStop(1, normalizeCanvasColor(endColor));
|
|
207
216
|
this.context.fillStyle = gradient;
|
|
208
217
|
this.context.fillRect(tx, ty, width, height);
|
|
@@ -264,6 +273,92 @@ export class CanvasRenderer extends CoreRenderer {
|
|
|
264
273
|
this.clearColor = normalizeCanvasColor(color);
|
|
265
274
|
}
|
|
266
275
|
|
|
276
|
+
override getTextureCoords(
|
|
277
|
+
node: CoreNode,
|
|
278
|
+
): import('../../textures/Texture.js').TextureCoords | undefined {
|
|
279
|
+
const texture = node.texture;
|
|
280
|
+
if (texture === null) {
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const ctxTexture =
|
|
285
|
+
texture.type === TextureType.subTexture
|
|
286
|
+
? (texture as SubTexture).parentTexture.ctxTexture
|
|
287
|
+
: texture.ctxTexture;
|
|
288
|
+
if (ctxTexture === undefined) {
|
|
289
|
+
return undefined;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const textureOptions = node.props.textureOptions;
|
|
293
|
+
|
|
294
|
+
// early exit for textures with no options unless its a subtexture
|
|
295
|
+
if (
|
|
296
|
+
texture.type !== TextureType.subTexture &&
|
|
297
|
+
textureOptions === undefined
|
|
298
|
+
) {
|
|
299
|
+
return { x1: 0, y1: 0, x2: 1, y2: 1 };
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
let x1 = 0,
|
|
303
|
+
y1 = 0,
|
|
304
|
+
x2 = 1,
|
|
305
|
+
y2 = 1;
|
|
306
|
+
if (texture.type === TextureType.subTexture) {
|
|
307
|
+
const { w: parentW, h: parentH } = (texture as SubTexture).parentTexture
|
|
308
|
+
.dimensions!;
|
|
309
|
+
const { x, y, w, h } = (texture as SubTexture).props;
|
|
310
|
+
x1 = x / parentW;
|
|
311
|
+
y1 = y / parentH;
|
|
312
|
+
x2 = x1 + w / parentW;
|
|
313
|
+
y2 = y1 + h / parentH;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (textureOptions !== undefined && textureOptions !== null) {
|
|
317
|
+
const resizeMode = textureOptions.resizeMode;
|
|
318
|
+
if (
|
|
319
|
+
resizeMode !== undefined &&
|
|
320
|
+
resizeMode.type === 'cover' &&
|
|
321
|
+
texture.dimensions !== null
|
|
322
|
+
) {
|
|
323
|
+
const dimensions =
|
|
324
|
+
texture.dimensions as import('../../../common/CommonTypes.js').Dimensions;
|
|
325
|
+
const w = node.props.w;
|
|
326
|
+
const h = node.props.h;
|
|
327
|
+
const scaleX = w / dimensions.w;
|
|
328
|
+
const scaleY = h / dimensions.h;
|
|
329
|
+
const scale = Math.max(scaleX, scaleY);
|
|
330
|
+
const precision = 1 / scale;
|
|
331
|
+
|
|
332
|
+
// Determine based on width
|
|
333
|
+
if (scaleX < scale) {
|
|
334
|
+
const desiredSize = precision * node.props.w;
|
|
335
|
+
x1 = (1 - desiredSize / dimensions.w) * (resizeMode.clipX ?? 0.5);
|
|
336
|
+
x2 = x1 + desiredSize / dimensions.w;
|
|
337
|
+
}
|
|
338
|
+
// Determine based on height
|
|
339
|
+
if (scaleY < scale) {
|
|
340
|
+
const desiredSize = precision * node.props.h;
|
|
341
|
+
y1 = (1 - desiredSize / dimensions.h) * (resizeMode.clipY ?? 0.5);
|
|
342
|
+
y2 = y1 + desiredSize / dimensions.h;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (textureOptions.flipX === true) {
|
|
347
|
+
[x1, x2] = [x2, x1];
|
|
348
|
+
}
|
|
349
|
+
if (textureOptions.flipY === true) {
|
|
350
|
+
[y1, y2] = [y2, y1];
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
x1,
|
|
356
|
+
y1,
|
|
357
|
+
x2,
|
|
358
|
+
y2,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
267
362
|
override updateViewport(): void {
|
|
268
363
|
// noop
|
|
269
364
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { CoreNode } from '../../CoreNode.js';
|
|
2
2
|
import { normalizeCanvasColor } from '../../lib/colorCache.js';
|
|
3
3
|
import type { Stage } from '../../Stage.js';
|
|
4
|
-
import type { QuadOptions } from '../CoreRenderer.js';
|
|
5
4
|
import { CoreShaderNode, type CoreShaderType } from '../CoreShaderNode.js';
|
|
6
5
|
|
|
7
6
|
export type CanvasShaderType<
|
|
@@ -11,7 +10,7 @@ export type CanvasShaderType<
|
|
|
11
10
|
render: (
|
|
12
11
|
this: CanvasShaderNode<T, C>,
|
|
13
12
|
ctx: CanvasRenderingContext2D,
|
|
14
|
-
|
|
13
|
+
node: CoreNode,
|
|
15
14
|
renderContext: () => void,
|
|
16
15
|
) => void;
|
|
17
16
|
update?: (this: CanvasShaderNode<T, C>, node: CoreNode) => void;
|
|
@@ -33,10 +33,10 @@ export class SdfRenderOp extends CoreRenderOp {
|
|
|
33
33
|
readonly renderer: WebGlRenderer,
|
|
34
34
|
readonly shader: WebGlShaderNode,
|
|
35
35
|
readonly quadBufferCollection: BufferCollection,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
readonly
|
|
39
|
-
readonly
|
|
36
|
+
readonly worldAlpha: number,
|
|
37
|
+
readonly clippingRect: RectWithValid,
|
|
38
|
+
readonly w: number,
|
|
39
|
+
readonly h: number,
|
|
40
40
|
readonly rtt: boolean,
|
|
41
41
|
public parentHasRenderTexture: boolean,
|
|
42
42
|
public framebufferDimensions: Dimensions | null,
|
|
@@ -70,8 +70,8 @@ export class SdfRenderOp extends CoreRenderOp {
|
|
|
70
70
|
const pixelRatio =
|
|
71
71
|
USE_RTT && this.parentHasRenderTexture ? 1 : stage.pixelRatio;
|
|
72
72
|
const clipX = Math.round(this.clippingRect.x * pixelRatio);
|
|
73
|
-
const clipWidth = Math.round(this.clippingRect.
|
|
74
|
-
const clipHeight = Math.round(this.clippingRect.
|
|
73
|
+
const clipWidth = Math.round(this.clippingRect.w * pixelRatio);
|
|
74
|
+
const clipHeight = Math.round(this.clippingRect.h * pixelRatio);
|
|
75
75
|
let clipY = Math.round(
|
|
76
76
|
options.canvas.height - clipHeight - this.clippingRect.y * pixelRatio,
|
|
77
77
|
);
|
|
@@ -79,7 +79,7 @@ export class SdfRenderOp extends CoreRenderOp {
|
|
|
79
79
|
// to be relative to the parent's framebuffer
|
|
80
80
|
if (USE_RTT && this.parentHasRenderTexture) {
|
|
81
81
|
clipY = this.framebufferDimensions
|
|
82
|
-
? this.framebufferDimensions.h - this.
|
|
82
|
+
? this.framebufferDimensions.h - this.h
|
|
83
83
|
: 0;
|
|
84
84
|
}
|
|
85
85
|
|
|
@@ -134,7 +134,7 @@ export class WebGlShaderProgram implements CoreShaderProgram {
|
|
|
134
134
|
return this.lifecycle.canBatch(node, currentRenderOp);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
const { time, worldAlpha,
|
|
137
|
+
const { time, worldAlpha, w, h } = node;
|
|
138
138
|
|
|
139
139
|
if (this.useTimeValue === true) {
|
|
140
140
|
if (time !== currentRenderOp.time) {
|
|
@@ -149,10 +149,7 @@ export class WebGlShaderProgram implements CoreShaderProgram {
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
if (this.useSystemDimensions === true) {
|
|
152
|
-
if (
|
|
153
|
-
width !== currentRenderOp.width ||
|
|
154
|
-
height !== currentRenderOp.height
|
|
155
|
-
) {
|
|
152
|
+
if (w !== currentRenderOp.w || h !== currentRenderOp.h) {
|
|
156
153
|
return false;
|
|
157
154
|
}
|
|
158
155
|
}
|
|
@@ -235,7 +232,7 @@ export class WebGlShaderProgram implements CoreShaderProgram {
|
|
|
235
232
|
}
|
|
236
233
|
|
|
237
234
|
if (this.useSystemDimensions === true) {
|
|
238
|
-
this.glw.uniform2f('u_dimensions', renderOp.
|
|
235
|
+
this.glw.uniform2f('u_dimensions', renderOp.w, renderOp.h);
|
|
239
236
|
}
|
|
240
237
|
|
|
241
238
|
const shader = renderOp.shader as WebGlShaderNode;
|
|
@@ -72,39 +72,35 @@ export const Border: CanvasShaderType<BorderProps, ComputedBorderValues> = {
|
|
|
72
72
|
this.computed.innerW = outerW - l - r;
|
|
73
73
|
this.computed.innerH = outerH - t - b;
|
|
74
74
|
},
|
|
75
|
-
render(ctx,
|
|
75
|
+
render(ctx, node, renderContext) {
|
|
76
76
|
renderContext();
|
|
77
77
|
const computed = this.computed as ComputedBorderValues;
|
|
78
|
+
const { tx, ty } = node.globalTransform!;
|
|
79
|
+
const { w, h } = node.props;
|
|
78
80
|
ctx.strokeStyle = computed.borderColor!;
|
|
79
81
|
if (computed.borderAsym === false && this.props!.w[0] > 0) {
|
|
80
82
|
ctx.lineWidth = this.props!.w[0];
|
|
81
83
|
ctx.beginPath();
|
|
82
84
|
ctx.strokeRect(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
tx + computed.outerX,
|
|
86
|
+
ty + computed.outerY,
|
|
87
|
+
w + computed.outerW,
|
|
88
|
+
h + computed.outerH,
|
|
87
89
|
);
|
|
88
90
|
return;
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
// Pre-calculate common values
|
|
92
|
-
const tx = quad.tx;
|
|
93
|
-
const ty = quad.ty;
|
|
94
|
-
const width = quad.width;
|
|
95
|
-
const height = quad.height;
|
|
96
|
-
|
|
97
93
|
// Calculate outer rectangle (including border)
|
|
98
94
|
const outerX = tx + computed.outerX;
|
|
99
95
|
const outerY = ty + computed.outerY;
|
|
100
|
-
const outerW =
|
|
101
|
-
const outerH =
|
|
96
|
+
const outerW = w + computed.outerW;
|
|
97
|
+
const outerH = h + computed.outerH;
|
|
102
98
|
|
|
103
99
|
// Calculate inner rectangle (excluding border)
|
|
104
100
|
const innerX = tx + computed.innerX;
|
|
105
101
|
const innerY = ty + computed.innerY;
|
|
106
|
-
const innerW =
|
|
107
|
-
const innerH =
|
|
102
|
+
const innerW = w + computed.innerW;
|
|
103
|
+
const innerH = h + computed.innerH;
|
|
108
104
|
|
|
109
105
|
// Use clip to subtract inner from outer
|
|
110
106
|
ctx.save();
|
|
@@ -27,8 +27,9 @@ export const HolePunch: CanvasShaderType<
|
|
|
27
27
|
ctx.save();
|
|
28
28
|
renderContext();
|
|
29
29
|
const { x, y, w, h } = this.props!;
|
|
30
|
+
const gt = quad.globalTransform!;
|
|
30
31
|
ctx.beginPath();
|
|
31
|
-
roundRect(ctx,
|
|
32
|
+
roundRect(ctx, gt.tx + x, gt.ty + y, w, h, this.computed.radius!);
|
|
32
33
|
ctx.closePath();
|
|
33
34
|
ctx.fillStyle = 'black';
|
|
34
35
|
ctx.globalCompositeOperation = 'destination-out';
|
|
@@ -31,17 +31,36 @@ export const LinearGradient: CanvasShaderType<
|
|
|
31
31
|
y0: line * Math.sin(angle) + nHeight * 0.5,
|
|
32
32
|
x1: line * Math.cos(angle + Math.PI) + nWidth * 0.5,
|
|
33
33
|
y1: line * Math.sin(angle + Math.PI) + nHeight * 0.5,
|
|
34
|
-
colors: this.props!.colors.map((value) =>
|
|
34
|
+
colors: this.props!.colors.map((value, i, arr) => {
|
|
35
|
+
const alpha = (value >>> 24) & 0xff;
|
|
36
|
+
if (alpha === 0) {
|
|
37
|
+
let nearestRGB = value & 0x00ffffff;
|
|
38
|
+
for (let step = 1; step < arr.length; step++) {
|
|
39
|
+
if (i - step >= 0 && ((arr[i - step]! >>> 24) & 0xff) > 0) {
|
|
40
|
+
nearestRGB = arr[i - step]! & 0x00ffffff;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
if (i + step < arr.length && ((arr[i + step]! >>> 24) & 0xff) > 0) {
|
|
44
|
+
nearestRGB = arr[i + step]! & 0x00ffffff;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
value = (value & 0xff000000) | nearestRGB;
|
|
49
|
+
}
|
|
50
|
+
return this.toColorString(value);
|
|
51
|
+
}),
|
|
35
52
|
};
|
|
36
53
|
},
|
|
37
|
-
render(ctx,
|
|
54
|
+
render(ctx, node, renderContext) {
|
|
38
55
|
renderContext();
|
|
39
56
|
const computed = this.computed as ComputedLinearGradientValues;
|
|
57
|
+
const { tx, ty } = node.globalTransform!;
|
|
58
|
+
const { w, h } = node.props;
|
|
40
59
|
const gradient = ctx.createLinearGradient(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
60
|
+
tx + computed.x0,
|
|
61
|
+
ty + computed.y0,
|
|
62
|
+
tx + computed.x1,
|
|
63
|
+
ty + computed.y1,
|
|
45
64
|
);
|
|
46
65
|
const colors = computed.colors;
|
|
47
66
|
const stops = this.props!.stops;
|
|
@@ -49,6 +68,6 @@ export const LinearGradient: CanvasShaderType<
|
|
|
49
68
|
gradient.addColorStop(stops[i]!, colors[i]!);
|
|
50
69
|
}
|
|
51
70
|
ctx.fillStyle = gradient;
|
|
52
|
-
ctx.fillRect(
|
|
71
|
+
ctx.fillRect(tx, ty, w, h);
|
|
53
72
|
},
|
|
54
73
|
};
|
|
@@ -39,12 +39,14 @@ export const RadialGradient: CanvasShaderType<
|
|
|
39
39
|
colors: props.colors.map((value) => this.toColorString(value)),
|
|
40
40
|
};
|
|
41
41
|
},
|
|
42
|
-
render(ctx,
|
|
42
|
+
render(ctx, node, renderContext) {
|
|
43
43
|
renderContext();
|
|
44
44
|
const { scaleX, scaleY, pivotX, pivotY, colors, size } = this
|
|
45
45
|
.computed as ComputedRadialGradientValues;
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
const { tx, ty } = node.globalTransform!;
|
|
47
|
+
const { w, h } = node.props;
|
|
48
|
+
let x = tx + pivotX;
|
|
49
|
+
let y = ty + pivotY;
|
|
48
50
|
const stops = this.props!.stops;
|
|
49
51
|
|
|
50
52
|
if (scaleX === scaleY) {
|
|
@@ -55,7 +57,7 @@ export const RadialGradient: CanvasShaderType<
|
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
ctx.fillStyle = gradient;
|
|
58
|
-
ctx.fillRect(
|
|
60
|
+
ctx.fillRect(tx, ty, w, h);
|
|
59
61
|
return;
|
|
60
62
|
}
|
|
61
63
|
|
|
@@ -70,12 +72,7 @@ export const RadialGradient: CanvasShaderType<
|
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
ctx.fillStyle = gradient;
|
|
73
|
-
ctx.fillRect(
|
|
74
|
-
quad.tx / scaleX,
|
|
75
|
-
quad.ty / scaleY,
|
|
76
|
-
quad.width / scaleX,
|
|
77
|
-
quad.height / scaleY,
|
|
78
|
-
);
|
|
75
|
+
ctx.fillRect(tx / scaleX, ty / scaleY, w / scaleX, h / scaleY);
|
|
79
76
|
|
|
80
77
|
ctx.restore();
|
|
81
78
|
},
|