@flighthq/effects 0.2.0 → 0.2.1-next.410.a23f189
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/bevelEffect.js +1 -1
- package/dist/bevelEffect.js.map +1 -1
- package/dist/blendEffect.d.ts +3 -0
- package/dist/blendEffect.d.ts.map +1 -0
- package/dist/blendEffect.js +10 -0
- package/dist/blendEffect.js.map +1 -0
- package/dist/blendModeMath.d.ts +6 -0
- package/dist/blendModeMath.d.ts.map +1 -0
- package/dist/blendModeMath.js +172 -0
- package/dist/blendModeMath.js.map +1 -0
- package/dist/compositeEffect.d.ts +3 -0
- package/dist/compositeEffect.d.ts.map +1 -0
- package/dist/compositeEffect.js +10 -0
- package/dist/compositeEffect.js.map +1 -0
- package/dist/compositeOperatorMath.d.ts +3 -0
- package/dist/compositeOperatorMath.d.ts.map +1 -0
- package/dist/compositeOperatorMath.js +65 -0
- package/dist/compositeOperatorMath.js.map +1 -0
- package/dist/dropShadowEffect.js +1 -1
- package/dist/dropShadowEffect.js.map +1 -1
- package/dist/gradientBevelEffect.js +1 -1
- package/dist/gradientBevelEffect.js.map +1 -1
- package/dist/gradientGlowEffect.js +1 -1
- package/dist/gradientGlowEffect.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/innerGlowEffect.js +1 -1
- package/dist/innerGlowEffect.js.map +1 -1
- package/dist/innerShadowEffect.js +1 -1
- package/dist/innerShadowEffect.js.map +1 -1
- package/dist/outerGlowEffect.js +1 -1
- package/dist/outerGlowEffect.js.map +1 -1
- package/dist/renderEffectDefaults.js +35 -6
- package/dist/renderEffectDefaults.js.map +1 -1
- package/dist/renderEffectInputs.d.ts.map +1 -1
- package/dist/renderEffectInputs.js +1 -0
- package/dist/renderEffectInputs.js.map +1 -1
- package/package.json +2 -2
- package/src/bevelEffect.test.ts +4 -1
- package/src/blendEffect.test.ts +23 -0
- package/src/blendModeMath.test.ts +160 -0
- package/src/compositeEffect.test.ts +21 -0
- package/src/compositeOperatorMath.test.ts +45 -0
- package/src/dropShadowEffect.test.ts +4 -1
- package/src/gradientBevelEffect.test.ts +8 -2
- package/src/gradientGlowEffect.test.ts +8 -2
- package/src/innerGlowEffect.test.ts +4 -0
- package/src/innerShadowEffect.test.ts +4 -0
- package/src/outerGlowEffect.test.ts +4 -1
- package/src/renderEffectDefaults.test.ts +9 -0
- package/dist/colorScienceMath.d.ts +0 -9
- package/dist/colorScienceMath.d.ts.map +0 -1
- package/dist/colorScienceMath.js +0 -135
- package/dist/colorScienceMath.js.map +0 -1
- package/src/colorScienceMath.test.ts +0 -160
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/effects",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1-next.410.a23f189",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/flighthq/flight.git",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@flighthq/types": "0.2.
|
|
35
|
+
"@flighthq/types": "0.2.1-next.410.a23f189"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"typescript": "^5.3.0"
|
package/src/bevelEffect.test.ts
CHANGED
|
@@ -6,6 +6,9 @@ describe('createBevelEffect', () => {
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
it('carries options', () => {
|
|
9
|
-
expect(createBevelEffect({ strength: 2 })).toMatchObject({
|
|
9
|
+
expect(createBevelEffect({ sourceMode: 'knockout', strength: 2 })).toMatchObject({
|
|
10
|
+
sourceMode: 'knockout',
|
|
11
|
+
strength: 2,
|
|
12
|
+
});
|
|
10
13
|
});
|
|
11
14
|
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AdvancedBlendMode } from '@flighthq/types';
|
|
2
|
+
|
|
3
|
+
import { createBlendEffect } from './blendEffect';
|
|
4
|
+
|
|
5
|
+
describe('createBlendEffect', () => {
|
|
6
|
+
it('builds a BlendEffect carrying the requested mode', () => {
|
|
7
|
+
const effect = createBlendEffect(AdvancedBlendMode.Overlay);
|
|
8
|
+
expect(effect.kind).toBe('BlendEffect');
|
|
9
|
+
expect(effect.mode).toBe('Overlay');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('spreads backdropKey and opacity options', () => {
|
|
13
|
+
const effect = createBlendEffect(AdvancedBlendMode.SoftLight, { backdropKey: 'scene.backdrop', opacity: 0.5 });
|
|
14
|
+
expect(effect.backdropKey).toBe('scene.backdrop');
|
|
15
|
+
expect(effect.opacity).toBe(0.5);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('leaves backdropKey and opacity undefined when omitted', () => {
|
|
19
|
+
const effect = createBlendEffect(AdvancedBlendMode.Hue);
|
|
20
|
+
expect(effect.backdropKey).toBeUndefined();
|
|
21
|
+
expect(effect.opacity).toBeUndefined();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { AdvancedBlendMode } from '@flighthq/types';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
blendNonSeparableRgb,
|
|
5
|
+
getAdvancedBlendRgb,
|
|
6
|
+
getSeparableBlendChannel,
|
|
7
|
+
isNonSeparableBlendMode,
|
|
8
|
+
} from './blendModeMath';
|
|
9
|
+
|
|
10
|
+
const LUM = (r: number, g: number, b: number): number => 0.3 * r + 0.59 * g + 0.11 * b;
|
|
11
|
+
const SAT = (r: number, g: number, b: number): number => Math.max(r, g, b) - Math.min(r, g, b);
|
|
12
|
+
|
|
13
|
+
describe('blendNonSeparableRgb', () => {
|
|
14
|
+
it('Luminosity replaces backdrop luma with source luma, preserving backdrop hue/sat', () => {
|
|
15
|
+
const out: [number, number, number] = [0, 0, 0];
|
|
16
|
+
const cb: [number, number, number] = [0.8, 0.2, 0.4];
|
|
17
|
+
const cs: [number, number, number] = [0.5, 0.5, 0.5];
|
|
18
|
+
blendNonSeparableRgb(AdvancedBlendMode.Luminosity, cb[0], cb[1], cb[2], cs[0], cs[1], cs[2], out);
|
|
19
|
+
// Result luma equals the source's luma.
|
|
20
|
+
expect(LUM(out[0], out[1], out[2])).toBeCloseTo(LUM(cs[0], cs[1], cs[2]), 5);
|
|
21
|
+
// Backdrop saturation is preserved (chroma range unchanged) since no channel clipped.
|
|
22
|
+
expect(SAT(out[0], out[1], out[2])).toBeCloseTo(SAT(cb[0], cb[1], cb[2]), 5);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('Color takes source hue+sat with backdrop luma', () => {
|
|
26
|
+
const out: [number, number, number] = [0, 0, 0];
|
|
27
|
+
const cb: [number, number, number] = [0.2, 0.2, 0.2]; // gray backdrop, luma 0.2
|
|
28
|
+
const cs: [number, number, number] = [0.9, 0.1, 0.1];
|
|
29
|
+
blendNonSeparableRgb(AdvancedBlendMode.Color, cb[0], cb[1], cb[2], cs[0], cs[1], cs[2], out);
|
|
30
|
+
expect(LUM(out[0], out[1], out[2])).toBeCloseTo(LUM(cb[0], cb[1], cb[2]), 5);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('Hue takes source hue, backdrop sat and luma', () => {
|
|
34
|
+
const out: [number, number, number] = [0, 0, 0];
|
|
35
|
+
const cb: [number, number, number] = [0.4, 0.5, 0.6];
|
|
36
|
+
const cs: [number, number, number] = [0.9, 0.2, 0.2];
|
|
37
|
+
blendNonSeparableRgb(AdvancedBlendMode.Hue, cb[0], cb[1], cb[2], cs[0], cs[1], cs[2], out);
|
|
38
|
+
expect(LUM(out[0], out[1], out[2])).toBeCloseTo(LUM(cb[0], cb[1], cb[2]), 5);
|
|
39
|
+
expect(SAT(out[0], out[1], out[2])).toBeCloseTo(SAT(cb[0], cb[1], cb[2]), 5);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('Saturation takes source sat, backdrop hue and luma', () => {
|
|
43
|
+
const out: [number, number, number] = [0, 0, 0];
|
|
44
|
+
const cb: [number, number, number] = [0.4, 0.5, 0.6];
|
|
45
|
+
const cs: [number, number, number] = [0.9, 0.2, 0.2]; // sat 0.7
|
|
46
|
+
blendNonSeparableRgb(AdvancedBlendMode.Saturation, cb[0], cb[1], cb[2], cs[0], cs[1], cs[2], out);
|
|
47
|
+
expect(SAT(out[0], out[1], out[2])).toBeCloseTo(SAT(cs[0], cs[1], cs[2]), 5);
|
|
48
|
+
expect(LUM(out[0], out[1], out[2])).toBeCloseTo(LUM(cb[0], cb[1], cb[2]), 5);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('keeps every channel in 0..1 after gamut clipping', () => {
|
|
52
|
+
const out: [number, number, number] = [0, 0, 0];
|
|
53
|
+
blendNonSeparableRgb(AdvancedBlendMode.Color, 0.95, 0.95, 0.95, 1, 0, 0, out);
|
|
54
|
+
for (const c of out) {
|
|
55
|
+
expect(c).toBeGreaterThanOrEqual(0);
|
|
56
|
+
expect(c).toBeLessThanOrEqual(1);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('falls through to the source triple for an unknown mode', () => {
|
|
61
|
+
const out: [number, number, number] = [0, 0, 0];
|
|
62
|
+
blendNonSeparableRgb('acme.Nope', 0.1, 0.2, 0.3, 0.7, 0.8, 0.9, out);
|
|
63
|
+
expect(out).toEqual([0.7, 0.8, 0.9]);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('getAdvancedBlendRgb', () => {
|
|
68
|
+
it('falls through to the source triple for a non-advanced mode', () => {
|
|
69
|
+
const out: [number, number, number] = [0, 0, 0];
|
|
70
|
+
// A fixed-function mode name is not an AdvancedBlendMode, so it takes the separable Normal path.
|
|
71
|
+
getAdvancedBlendRgb('Multiply', 0.5, 0.5, 0.5, 0.2, 0.3, 0.4, out);
|
|
72
|
+
expect(out).toEqual([0.2, 0.3, 0.4]);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('computes Difference per channel', () => {
|
|
76
|
+
const out: [number, number, number] = [0, 0, 0];
|
|
77
|
+
getAdvancedBlendRgb(AdvancedBlendMode.Difference, 0.8, 0.5, 0.2, 0.3, 0.5, 0.9, out);
|
|
78
|
+
expect(out[0]).toBeCloseTo(0.5, 5);
|
|
79
|
+
expect(out[1]).toBeCloseTo(0, 5);
|
|
80
|
+
expect(out[2]).toBeCloseTo(0.7, 5);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('routes HSL modes through the non-separable path', () => {
|
|
84
|
+
const out: [number, number, number] = [0, 0, 0];
|
|
85
|
+
getAdvancedBlendRgb(AdvancedBlendMode.Luminosity, 0.8, 0.2, 0.4, 0.5, 0.5, 0.5, out);
|
|
86
|
+
expect(LUM(out[0], out[1], out[2])).toBeCloseTo(0.5, 5);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('getSeparableBlendChannel', () => {
|
|
91
|
+
it('Overlay equals HardLight with operands swapped', () => {
|
|
92
|
+
const cb = 0.6;
|
|
93
|
+
const cs = 0.3;
|
|
94
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.Overlay, cb, cs)).toBeCloseTo(
|
|
95
|
+
getSeparableBlendChannel(AdvancedBlendMode.HardLight, cs, cb),
|
|
96
|
+
6,
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('Difference is the absolute channel distance', () => {
|
|
101
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.Difference, 0.8, 0.3)).toBeCloseTo(0.5, 6);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('Exclusion(x, 0.5) collapses to 0.5 regardless of backdrop', () => {
|
|
105
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.Exclusion, 0.2, 0.5)).toBeCloseTo(0.5, 6);
|
|
106
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.Exclusion, 0.9, 0.5)).toBeCloseTo(0.5, 6);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('ColorDodge clamps to white when source is 1 and stays 0 for a black backdrop', () => {
|
|
110
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.ColorDodge, 0.4, 1)).toBe(1);
|
|
111
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.ColorDodge, 0, 0.5)).toBe(0);
|
|
112
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.ColorDodge, 0.25, 0.5)).toBeCloseTo(0.5, 6);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('ColorBurn clamps to black when source is 0 and stays 1 for a white backdrop', () => {
|
|
116
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.ColorBurn, 0.6, 0)).toBe(0);
|
|
117
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.ColorBurn, 1, 0.5)).toBe(1);
|
|
118
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.ColorBurn, 0.75, 0.5)).toBeCloseTo(0.5, 6);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('SoftLight leaves the backdrop unchanged for a mid-gray source', () => {
|
|
122
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.SoftLight, 0.6, 0.5)).toBeCloseTo(0.6, 6);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('HardLight over a 0.5 source is a straight overlay of the backdrop', () => {
|
|
126
|
+
// cs = 0.5 sits on the branch boundary; both branches agree there.
|
|
127
|
+
expect(getSeparableBlendChannel(AdvancedBlendMode.HardLight, 0.4, 0.5)).toBeCloseTo(0.4, 6);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('returns the source channel (Normal) for an unknown mode', () => {
|
|
131
|
+
expect(getSeparableBlendChannel('acme.Nope', 0.2, 0.7)).toBe(0.7);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('isNonSeparableBlendMode', () => {
|
|
136
|
+
it('is true only for the four HSL modes', () => {
|
|
137
|
+
for (const mode of [
|
|
138
|
+
AdvancedBlendMode.Hue,
|
|
139
|
+
AdvancedBlendMode.Saturation,
|
|
140
|
+
AdvancedBlendMode.Color,
|
|
141
|
+
AdvancedBlendMode.Luminosity,
|
|
142
|
+
]) {
|
|
143
|
+
expect(isNonSeparableBlendMode(mode)).toBe(true);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('is false for the separable modes', () => {
|
|
148
|
+
for (const mode of [
|
|
149
|
+
AdvancedBlendMode.Overlay,
|
|
150
|
+
AdvancedBlendMode.HardLight,
|
|
151
|
+
AdvancedBlendMode.SoftLight,
|
|
152
|
+
AdvancedBlendMode.Difference,
|
|
153
|
+
AdvancedBlendMode.Exclusion,
|
|
154
|
+
AdvancedBlendMode.ColorDodge,
|
|
155
|
+
AdvancedBlendMode.ColorBurn,
|
|
156
|
+
]) {
|
|
157
|
+
expect(isNonSeparableBlendMode(mode)).toBe(false);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CompositeOperator } from '@flighthq/types';
|
|
2
|
+
|
|
3
|
+
import { createCompositeEffect } from './compositeEffect';
|
|
4
|
+
|
|
5
|
+
describe('createCompositeEffect', () => {
|
|
6
|
+
it('builds a CompositeEffect carrying the requested operator', () => {
|
|
7
|
+
const effect = createCompositeEffect(CompositeOperator.DestinationOut);
|
|
8
|
+
expect(effect.kind).toBe('CompositeEffect');
|
|
9
|
+
expect(effect.operator).toBe('DestinationOut');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('spreads the backdropKey option', () => {
|
|
13
|
+
const effect = createCompositeEffect(CompositeOperator.DestinationIn, { backdropKey: 'scene.backdrop' });
|
|
14
|
+
expect(effect.backdropKey).toBe('scene.backdrop');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('leaves backdropKey undefined when omitted', () => {
|
|
18
|
+
const effect = createCompositeEffect(CompositeOperator.Xor);
|
|
19
|
+
expect(effect.backdropKey).toBeUndefined();
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { CompositeOperator } from '@flighthq/types';
|
|
2
|
+
|
|
3
|
+
import { getCompositeOperatorFactors } from './compositeOperatorMath';
|
|
4
|
+
|
|
5
|
+
function factors(operator: CompositeOperator, as: number, ab: number): [number, number] {
|
|
6
|
+
const out: [number, number] = [0, 0];
|
|
7
|
+
getCompositeOperatorFactors(operator, as, ab, out);
|
|
8
|
+
return out;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
describe('getCompositeOperatorFactors', () => {
|
|
12
|
+
it('gives source-over its canonical [1, 1 - as]', () => {
|
|
13
|
+
expect(factors(CompositeOperator.SourceOver, 0.6, 0.4)).toEqual([1, 1 - 0.6]);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('erases (DestinationOut) by keeping only the backdrop scaled by 1 - as', () => {
|
|
17
|
+
expect(factors(CompositeOperator.DestinationOut, 0.75, 1)).toEqual([0, 1 - 0.75]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('masks (DestinationIn) by keeping only the backdrop scaled by as', () => {
|
|
21
|
+
expect(factors(CompositeOperator.DestinationIn, 0.75, 1)).toEqual([0, 0.75]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('copies the source and drops the backdrop', () => {
|
|
25
|
+
expect(factors(CompositeOperator.Copy, 0.3, 0.9)).toEqual([1, 0]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('clears both contributions', () => {
|
|
29
|
+
expect(factors(CompositeOperator.Clear, 0.3, 0.9)).toEqual([0, 0]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('xors to the mutually-uncovered regions', () => {
|
|
33
|
+
expect(factors(CompositeOperator.Xor, 0.5, 0.25)).toEqual([1 - 0.25, 1 - 0.5]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('falls through to source-over for an unknown (vendor) operator', () => {
|
|
37
|
+
expect(factors('acme.custom', 0.6, 0.4)).toEqual([1, 1 - 0.6]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('is alias-safe writing into a supplied out array', () => {
|
|
41
|
+
const out: [number, number] = [9, 9];
|
|
42
|
+
getCompositeOperatorFactors(CompositeOperator.DestinationOver, 0.2, 0.8, out);
|
|
43
|
+
expect(out).toEqual([1 - 0.8, 1]);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -6,6 +6,9 @@ describe('createDropShadowEffect', () => {
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
it('carries options', () => {
|
|
9
|
-
expect(createDropShadowEffect({ strength: 2 })).toMatchObject({
|
|
9
|
+
expect(createDropShadowEffect({ sourceMode: 'knockout', strength: 2 })).toMatchObject({
|
|
10
|
+
sourceMode: 'knockout',
|
|
11
|
+
strength: 2,
|
|
12
|
+
});
|
|
10
13
|
});
|
|
11
14
|
});
|
|
@@ -9,7 +9,13 @@ describe('createGradientBevelEffect', () => {
|
|
|
9
9
|
|
|
10
10
|
it('carries options', () => {
|
|
11
11
|
expect(
|
|
12
|
-
createGradientBevelEffect({
|
|
13
|
-
|
|
12
|
+
createGradientBevelEffect({
|
|
13
|
+
colors: [0xff0000, 0x00ff00],
|
|
14
|
+
alphas: [1, 1],
|
|
15
|
+
ratios: [0, 255],
|
|
16
|
+
sourceMode: 'hide',
|
|
17
|
+
strength: 2,
|
|
18
|
+
}),
|
|
19
|
+
).toMatchObject({ sourceMode: 'hide', strength: 2 });
|
|
14
20
|
});
|
|
15
21
|
});
|
|
@@ -9,7 +9,13 @@ describe('createGradientGlowEffect', () => {
|
|
|
9
9
|
|
|
10
10
|
it('carries options', () => {
|
|
11
11
|
expect(
|
|
12
|
-
createGradientGlowEffect({
|
|
13
|
-
|
|
12
|
+
createGradientGlowEffect({
|
|
13
|
+
colors: [0xff0000, 0x00ff00],
|
|
14
|
+
alphas: [1, 1],
|
|
15
|
+
ratios: [0, 255],
|
|
16
|
+
sourceMode: 'knockout',
|
|
17
|
+
strength: 2,
|
|
18
|
+
}),
|
|
19
|
+
).toMatchObject({ sourceMode: 'knockout', strength: 2 });
|
|
14
20
|
});
|
|
15
21
|
});
|
|
@@ -8,4 +8,8 @@ describe('createInnerGlowEffect', () => {
|
|
|
8
8
|
it('carries options', () => {
|
|
9
9
|
expect(createInnerGlowEffect({ strength: 2 })).toMatchObject({ strength: 2 });
|
|
10
10
|
});
|
|
11
|
+
|
|
12
|
+
it('carries source mode', () => {
|
|
13
|
+
expect(createInnerGlowEffect({ sourceMode: 'hide' })).toMatchObject({ sourceMode: 'hide' });
|
|
14
|
+
});
|
|
11
15
|
});
|
|
@@ -8,4 +8,8 @@ describe('createInnerShadowEffect', () => {
|
|
|
8
8
|
it('carries options', () => {
|
|
9
9
|
expect(createInnerShadowEffect({ strength: 2 })).toMatchObject({ strength: 2 });
|
|
10
10
|
});
|
|
11
|
+
|
|
12
|
+
it('carries source mode', () => {
|
|
13
|
+
expect(createInnerShadowEffect({ sourceMode: 'hide' })).toMatchObject({ sourceMode: 'hide' });
|
|
14
|
+
});
|
|
11
15
|
});
|
|
@@ -6,6 +6,9 @@ describe('createOuterGlowEffect', () => {
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
it('carries options', () => {
|
|
9
|
-
expect(createOuterGlowEffect({ strength: 2 })).toMatchObject({
|
|
9
|
+
expect(createOuterGlowEffect({ sourceMode: 'hide', strength: 2 })).toMatchObject({
|
|
10
|
+
sourceMode: 'hide',
|
|
11
|
+
strength: 2,
|
|
12
|
+
});
|
|
10
13
|
});
|
|
11
14
|
});
|
|
@@ -19,6 +19,15 @@ describe('getRenderEffectDefaults', () => {
|
|
|
19
19
|
expect(d.operator).toBe('aces');
|
|
20
20
|
expect(d.exposure).toBe(0);
|
|
21
21
|
});
|
|
22
|
+
it('returns sourceMode draw for composite source-mode effects', () => {
|
|
23
|
+
expect(getRenderEffectDefaults('DropShadowEffect').sourceMode).toBe('draw');
|
|
24
|
+
expect(getRenderEffectDefaults('OuterGlowEffect').sourceMode).toBe('draw');
|
|
25
|
+
expect(getRenderEffectDefaults('InnerGlowEffect').sourceMode).toBe('draw');
|
|
26
|
+
expect(getRenderEffectDefaults('InnerShadowEffect').sourceMode).toBe('draw');
|
|
27
|
+
expect(getRenderEffectDefaults('BevelEffect').sourceMode).toBe('draw');
|
|
28
|
+
expect(getRenderEffectDefaults('GradientGlowEffect').sourceMode).toBe('draw');
|
|
29
|
+
expect(getRenderEffectDefaults('GradientBevelEffect').sourceMode).toBe('draw');
|
|
30
|
+
});
|
|
22
31
|
it('returns a fresh copy each call (mutations do not persist)', () => {
|
|
23
32
|
const d1 = getRenderEffectDefaults('BloomEffect');
|
|
24
33
|
const d2 = getRenderEffectDefaults('BloomEffect');
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export declare function computeHslToRgb(h: number, s: number, l: number, out: [number, number, number]): void;
|
|
2
|
-
export declare function computeLinearToSrgb(x: number): number;
|
|
3
|
-
export declare function computeOklabToRgb(L: number, a: number, b: number, out: [number, number, number]): void;
|
|
4
|
-
export declare function computeRgbToHsl(r: number, g: number, b: number, out: [number, number, number]): void;
|
|
5
|
-
export declare function computeRgbToOklab(r: number, g: number, b: number, out: [number, number, number]): void;
|
|
6
|
-
export declare function computeSrgbToLinear(x: number): number;
|
|
7
|
-
export declare function getRec2020LuminanceWeights(out: [number, number, number]): void;
|
|
8
|
-
export declare function getRec709LuminanceWeights(out: [number, number, number]): void;
|
|
9
|
-
//# sourceMappingURL=colorScienceMath.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"colorScienceMath.d.ts","sourceRoot":"","sources":["../src/colorScienceMath.ts"],"names":[],"mappings":"AAMA,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAoCpG;AAID,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrD;AAGD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAatG;AAID,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAwBpG;AAKD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAatG;AAID,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrD;AAID,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAI9E;AAID,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAI7E"}
|
package/dist/colorScienceMath.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
// Color-science recipe math. Complete working-space functions for HDR rendering, color grading,
|
|
2
|
-
// and perceptual operations. All functions are alias-safe and zero-allocation (out-param pattern).
|
|
3
|
-
// These are the substrate-agnostic primitives shared across all backends.
|
|
4
|
-
// Converts HSL [h∈[0..360), s∈[0..1], l∈[0..1]] to sRGB [0..1]. Writes into `out`.
|
|
5
|
-
// Alias-safe.
|
|
6
|
-
export function computeHslToRgb(h, s, l, out) {
|
|
7
|
-
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
8
|
-
const hh = (((h % 360) + 360) % 360) / 60;
|
|
9
|
-
const x = c * (1 - Math.abs((hh % 2) - 1));
|
|
10
|
-
let r1;
|
|
11
|
-
let g1;
|
|
12
|
-
let b1;
|
|
13
|
-
if (hh < 1) {
|
|
14
|
-
r1 = c;
|
|
15
|
-
g1 = x;
|
|
16
|
-
b1 = 0;
|
|
17
|
-
}
|
|
18
|
-
else if (hh < 2) {
|
|
19
|
-
r1 = x;
|
|
20
|
-
g1 = c;
|
|
21
|
-
b1 = 0;
|
|
22
|
-
}
|
|
23
|
-
else if (hh < 3) {
|
|
24
|
-
r1 = 0;
|
|
25
|
-
g1 = c;
|
|
26
|
-
b1 = x;
|
|
27
|
-
}
|
|
28
|
-
else if (hh < 4) {
|
|
29
|
-
r1 = 0;
|
|
30
|
-
g1 = x;
|
|
31
|
-
b1 = c;
|
|
32
|
-
}
|
|
33
|
-
else if (hh < 5) {
|
|
34
|
-
r1 = x;
|
|
35
|
-
g1 = 0;
|
|
36
|
-
b1 = c;
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
r1 = c;
|
|
40
|
-
g1 = 0;
|
|
41
|
-
b1 = x;
|
|
42
|
-
}
|
|
43
|
-
const m = l - c / 2;
|
|
44
|
-
out[0] = r1 + m;
|
|
45
|
-
out[1] = g1 + m;
|
|
46
|
-
out[2] = b1 + m;
|
|
47
|
-
}
|
|
48
|
-
// sRGB transfer function: converts a single linear-light channel value to gamma-encoded sRGB.
|
|
49
|
-
// The piecewise IEC 61966-2-1 formula. Input in [0..∞], output in [0..1].
|
|
50
|
-
export function computeLinearToSrgb(x) {
|
|
51
|
-
const v = Math.max(0, x);
|
|
52
|
-
return v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055;
|
|
53
|
-
}
|
|
54
|
-
// Converts Oklab back to linear sRGB [0..1]. Alias-safe.
|
|
55
|
-
export function computeOklabToRgb(L, a, b, out) {
|
|
56
|
-
// Oklab → LMS.
|
|
57
|
-
const lc = L + 0.3963377774 * a + 0.2158037573 * b;
|
|
58
|
-
const mc = L - 0.1055613458 * a - 0.0638541728 * b;
|
|
59
|
-
const sc = L - 0.0894841775 * a - 1.291485548 * b;
|
|
60
|
-
// Cube.
|
|
61
|
-
const l = lc * lc * lc;
|
|
62
|
-
const m = mc * mc * mc;
|
|
63
|
-
const s = sc * sc * sc;
|
|
64
|
-
// LMS → linear sRGB.
|
|
65
|
-
out[0] = Math.max(0, 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s);
|
|
66
|
-
out[1] = Math.max(0, -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s);
|
|
67
|
-
out[2] = Math.max(0, -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s);
|
|
68
|
-
}
|
|
69
|
-
// Converts sRGB [0..1] to HSL [h∈[0..360), s∈[0..1], l∈[0..1]]. Writes into `out`.
|
|
70
|
-
// Alias-safe: reads all inputs before writing.
|
|
71
|
-
export function computeRgbToHsl(r, g, b, out) {
|
|
72
|
-
const rc = Math.max(0, Math.min(1, r));
|
|
73
|
-
const gc = Math.max(0, Math.min(1, g));
|
|
74
|
-
const bc = Math.max(0, Math.min(1, b));
|
|
75
|
-
const max = Math.max(rc, gc, bc);
|
|
76
|
-
const min = Math.min(rc, gc, bc);
|
|
77
|
-
const d = max - min;
|
|
78
|
-
const l = (max + min) / 2;
|
|
79
|
-
let h = 0;
|
|
80
|
-
let s = 0;
|
|
81
|
-
if (d > 1e-10) {
|
|
82
|
-
s = d / (1 - Math.abs(2 * l - 1));
|
|
83
|
-
if (max === rc) {
|
|
84
|
-
h = ((gc - bc) / d + 6) % 6;
|
|
85
|
-
}
|
|
86
|
-
else if (max === gc) {
|
|
87
|
-
h = (bc - rc) / d + 2;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
h = (rc - gc) / d + 4;
|
|
91
|
-
}
|
|
92
|
-
h *= 60;
|
|
93
|
-
}
|
|
94
|
-
out[0] = h;
|
|
95
|
-
out[1] = s;
|
|
96
|
-
out[2] = l;
|
|
97
|
-
}
|
|
98
|
-
// Converts linear sRGB [0..1] to Oklab [L∈[0..1], a∈~[-0.5..0.5], b∈~[-0.5..0.5]].
|
|
99
|
-
// Oklab is a perceptually uniform space; changes in L, a, b produce visually equal steps.
|
|
100
|
-
// Reference: Ottosson 2020. Alias-safe.
|
|
101
|
-
export function computeRgbToOklab(r, g, b, out) {
|
|
102
|
-
// sRGB (linear) → LMS via a 3×3 matrix.
|
|
103
|
-
const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
|
104
|
-
const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
|
105
|
-
const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
|
106
|
-
// Cube-root compress.
|
|
107
|
-
const lc = Math.cbrt(Math.max(0, l));
|
|
108
|
-
const mc = Math.cbrt(Math.max(0, m));
|
|
109
|
-
const sc = Math.cbrt(Math.max(0, s));
|
|
110
|
-
// LMS → Oklab.
|
|
111
|
-
out[0] = 0.2104542553 * lc + 0.793617785 * mc - 0.0040720468 * sc;
|
|
112
|
-
out[1] = 1.9779984951 * lc - 2.428592205 * mc + 0.4505937099 * sc;
|
|
113
|
-
out[2] = 0.0259040371 * lc + 0.7827717662 * mc - 0.808675766 * sc;
|
|
114
|
-
}
|
|
115
|
-
// sRGB transfer function: converts a gamma-encoded sRGB channel to linear light.
|
|
116
|
-
// The piecewise IEC 61966-2-1 inverse. Input in [0..1], output in [0..∞).
|
|
117
|
-
export function computeSrgbToLinear(x) {
|
|
118
|
-
const v = Math.max(0, x);
|
|
119
|
-
return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
120
|
-
}
|
|
121
|
-
// Rec. 2020 luminance weights (ITU-R BT.2020). Writes [r, g, b] weights into `out`.
|
|
122
|
-
// L = 0.2627 * R + 0.6780 * G + 0.0593 * B.
|
|
123
|
-
export function getRec2020LuminanceWeights(out) {
|
|
124
|
-
out[0] = 0.2627;
|
|
125
|
-
out[1] = 0.678;
|
|
126
|
-
out[2] = 0.0593;
|
|
127
|
-
}
|
|
128
|
-
// Rec. 709 / sRGB luminance weights (ITU-R BT.709). Writes [r, g, b] weights into `out`.
|
|
129
|
-
// L = 0.2126 * R + 0.7152 * G + 0.0722 * B.
|
|
130
|
-
export function getRec709LuminanceWeights(out) {
|
|
131
|
-
out[0] = 0.2126;
|
|
132
|
-
out[1] = 0.7152;
|
|
133
|
-
out[2] = 0.0722;
|
|
134
|
-
}
|
|
135
|
-
//# sourceMappingURL=colorScienceMath.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"colorScienceMath.js","sourceRoot":"","sources":["../src/colorScienceMath.ts"],"names":[],"mappings":"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"}
|