├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ ├── BUG-REPORT.yml
│ └── FEATURE-REQUEST.yml
└── workflows
│ ├── examples.yml
│ ├── inactive.yaml
│ └── tests.yml
├── .gitignore
├── .husky
└── pre-commit
├── .npmrc
├── .prettierignore
├── .prettierrc.json
├── .vscode
├── extensions.json
└── settings.json
├── BROWSERS.md
├── CONTRIBUTING.md
├── COPYING
├── Dockerfile
├── LICENSE
├── NOTICE
├── README.md
├── RELEASE.md
├── docs
├── CustomShaderEffectTexture.md
├── ManualRegressionTests.md
├── NodeDependencyGraph.md
├── example-projects
│ └── custom-shader-effect-texture
│ │ ├── index.html
│ │ ├── package.json
│ │ ├── pnpm-lock.yaml
│ │ ├── pnpm-workspace.yaml
│ │ ├── src
│ │ ├── MyCustomShader.ts
│ │ ├── MyCustomTexture.ts
│ │ ├── assets
│ │ │ └── robot.png
│ │ ├── index.ts
│ │ └── vite-env.d.ts
│ │ ├── tsconfig.cfg.json
│ │ ├── tsconfig.json
│ │ └── vite.config.ts
└── images
│ ├── dependency-graph.png
│ └── dependency-graph.txt
├── eslint.config.js
├── examples
├── .npmrc
├── README.md
├── assets
│ ├── elevator.png
│ ├── elevator.svg
│ ├── green-100.png
│ ├── green-25.png
│ ├── green-50.png
│ ├── green-50.psd
│ ├── lightning.png
│ ├── lightning.svg
│ ├── red-100.png
│ ├── red-25.png
│ ├── red-50.png
│ ├── robot
│ │ ├── elevator-background.png
│ │ ├── elevator-door-bottom-top-floor.png
│ │ ├── elevator-door-left-ground-floor.png
│ │ ├── elevator-door-right-ground-floor.png
│ │ ├── elevator-door-shadow-ground-floor.png
│ │ ├── elevator-door-top-top-floor.png
│ │ ├── environment.png
│ │ ├── robot-shadow.png
│ │ └── robot.png
│ ├── rocko.png
│ ├── rocko.svg
│ ├── rocko2.svg
│ ├── spritemap.png
│ ├── test-etc1.pvr
│ ├── test-s3tc.ktx
│ ├── testscreen.png
│ ├── testscreen.svg
│ └── testscreen_rotated.png
├── common
│ ├── Character.ts
│ ├── Component.ts
│ ├── ExampleSettings.ts
│ ├── LocalStorage.ts
│ ├── LoremIpsum.ts
│ ├── MemMonitor.ts
│ ├── PageContainer.ts
│ ├── StatTracker.ts
│ ├── constructTestRow.ts
│ ├── installFonts.ts
│ ├── installShaders.ts
│ ├── paginateTestRows.ts
│ ├── setupMathRandom.ts
│ └── utils.ts
├── index.html
├── index.ts
├── package.json
├── public
│ └── fonts
│ │ ├── NotoSans-Bold.ttf
│ │ ├── NotoSans-Regular.ssdf.json
│ │ ├── NotoSans-Regular.ssdf.png
│ │ ├── NotoSans-Regular.ttf
│ │ ├── Ubuntu-Bold.msdf.json
│ │ ├── Ubuntu-Bold.msdf.png
│ │ ├── Ubuntu-Bold.ssdf.json
│ │ ├── Ubuntu-Bold.ssdf.png
│ │ ├── Ubuntu-Bold.ttf
│ │ ├── Ubuntu-Regular.msdf.json
│ │ ├── Ubuntu-Regular.msdf.png
│ │ ├── Ubuntu-Regular.ssdf.json
│ │ ├── Ubuntu-Regular.ssdf.png
│ │ └── Ubuntu-Regular.ttf
├── tests
│ ├── absolute-position.ts
│ ├── alignment.ts
│ ├── alpha-blending.ts
│ ├── alpha.ts
│ ├── animation-events.ts
│ ├── animation.ts
│ ├── child-positioning.ts
│ ├── clear-color-setting.ts
│ ├── clipping-mutations.ts
│ ├── clipping.ts
│ ├── destroy.ts
│ ├── detect-touch.ts
│ ├── gradient.ts
│ ├── inspector.ts
│ ├── mount-pivot.ts
│ ├── no-rtt.ts
│ ├── quads-rendered.ts
│ ├── render-bounds.ts
│ ├── render-settings.ts
│ ├── resize-mode.ts
│ ├── robot.ts
│ ├── rotation.ts
│ ├── rtt-dimension.ts
│ ├── rtt-nested-clipping.ts
│ ├── rtt-reflection.ts
│ ├── rtt-spritemap.ts
│ ├── rtt.ts
│ ├── scaling-animations.ts
│ ├── scaling.ts
│ ├── shader-animation.ts
│ ├── shader-border.ts
│ ├── shader-hole-punch.ts
│ ├── shader-linear-gradient.ts
│ ├── shader-radial-gradient.ts
│ ├── shader-rounded.ts
│ ├── shader-shadow.ts
│ ├── stress-images.ts
│ ├── stress-mix.ts
│ ├── stress-multi-level-bounds.ts
│ ├── stress-multi-level-clipping.ts
│ ├── stress-multi-level.ts
│ ├── stress-multi-texture.ts
│ ├── stress-single-level-text.ts
│ ├── stress-single-level.ts
│ ├── stress-textures.ts
│ ├── test.ts
│ ├── text-align.ts
│ ├── text-alpha.ts
│ ├── text-baseline.ts
│ ├── text-canvas-font-no-metrics.ts
│ ├── text-canvas.ts
│ ├── text-contain.ts
│ ├── text-dimensions.ts
│ ├── text-events.ts
│ ├── text-layout-consistency-modified-metrics.ts
│ ├── text-layout-consistency.ts
│ ├── text-line-height.ts
│ ├── text-max-lines.ts
│ ├── text-mixed.ts
│ ├── text-offscreen-move.ts
│ ├── text-overflow-suffix.ts
│ ├── text-rotation.ts
│ ├── text-scaling.ts
│ ├── text-ssdf.ts
│ ├── text-vertical-align.ts
│ ├── text-wordbreak.ts
│ ├── text-zwsp.ts
│ ├── text.ts
│ ├── texture-autosize.ts
│ ├── texture-base64.ts
│ ├── texture-cleanup-critical.ts
│ ├── texture-cleanup-idle.ts
│ ├── texture-factory.ts
│ ├── texture-memory-allocation.ts
│ ├── texture-memory-rtt.ts
│ ├── texture-memory-spritemap.ts
│ ├── texture-reload.ts
│ ├── texture-source.ts
│ ├── texture-spritemap.ts
│ ├── texture-svg.ts
│ ├── textures.ts
│ ├── tx-compression.ts
│ ├── viewport-boundsmargin.ts
│ ├── viewport-events-canvas.ts
│ ├── viewport-events.ts
│ ├── viewport-largebound.ts
│ ├── viewport-memory.ts
│ ├── viewport-strictbounds.ts
│ └── zIndex.ts
├── tsconfig.json
├── vite-env.d.ts
└── vite.config.ts
├── exports
├── canvas-shaders.ts
├── canvas.ts
├── index.ts
├── inspector.ts
├── utils.ts
├── webgl-shaders.ts
└── webgl.ts
├── package.json
├── performance
├── .gitignore
├── bun.lockb
├── index.ts
├── package.json
├── readme.md
├── src
│ ├── CoreNode.ts
│ ├── ImageTexture.ts
│ ├── Tree.ts
│ ├── WebGlContextWrapper.ts
│ └── utils
│ │ └── types.ts
└── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── src
├── common
│ ├── CommonTypes.ts
│ ├── EventEmitter.ts
│ ├── IAnimationController.ts
│ └── IEventEmitter.ts
├── core
│ ├── CoreNode.test.ts
│ ├── CoreNode.ts
│ ├── CoreShaderManager.ts
│ ├── CoreTextNode.ts
│ ├── CoreTextureManager.ts
│ ├── Stage.ts
│ ├── TextureMemoryManager.ts
│ ├── animations
│ │ ├── AnimationManager.ts
│ │ ├── CoreAnimation.ts
│ │ └── CoreAnimationController.ts
│ ├── lib
│ │ ├── ContextSpy.ts
│ │ ├── ImageWorker.ts
│ │ ├── Matrix3d.ts
│ │ ├── RenderCoords.ts
│ │ ├── WebGlContextWrapper.ts
│ │ ├── textureCompression.ts
│ │ ├── textureSvg.ts
│ │ ├── utils.ts
│ │ └── validateImageBitmap.ts
│ ├── platforms
│ │ ├── Platform.ts
│ │ └── web
│ │ │ └── WebPlatform.ts
│ ├── renderers
│ │ ├── CoreContextTexture.ts
│ │ ├── CoreRenderOp.ts
│ │ ├── CoreRenderer.ts
│ │ ├── CoreShaderNode.ts
│ │ ├── CoreShaderProgram.ts
│ │ ├── canvas
│ │ │ ├── CanvasRenderer.ts
│ │ │ ├── CanvasShaderNode.ts
│ │ │ ├── CanvasTexture.ts
│ │ │ └── internal
│ │ │ │ ├── C2DShaderUtils.ts
│ │ │ │ └── ColorUtils.ts
│ │ └── webgl
│ │ │ ├── WebGlCtxRenderTexture.ts
│ │ │ ├── WebGlCtxSubTexture.ts
│ │ │ ├── WebGlCtxTexture.ts
│ │ │ ├── WebGlRenderOp.ts
│ │ │ ├── WebGlRenderer.ts
│ │ │ ├── WebGlShaderNode.ts
│ │ │ ├── WebGlShaderProgram.ts
│ │ │ └── internal
│ │ │ ├── BufferCollection.ts
│ │ │ ├── RendererUtils.ts
│ │ │ ├── ShaderUtils.ts
│ │ │ └── WebGlUtils.ts
│ ├── shaders
│ │ ├── canvas
│ │ │ ├── Border.ts
│ │ │ ├── HolePunch.ts
│ │ │ ├── LinearGradient.ts
│ │ │ ├── RadialGradient.ts
│ │ │ ├── Rounded.ts
│ │ │ ├── RoundedWithBorder.ts
│ │ │ ├── RoundedWithBorderAndShadow.ts
│ │ │ ├── RoundedWithShadow.ts
│ │ │ ├── Shadow.ts
│ │ │ └── utils
│ │ │ │ └── render.ts
│ │ ├── templates
│ │ │ ├── BorderTemplate.ts
│ │ │ ├── HolePunchTemplate.ts
│ │ │ ├── LinearGradientTemplate.ts
│ │ │ ├── RadialGradientTemplate.ts
│ │ │ ├── RoundedTemplate.ts
│ │ │ ├── RoundedWithBorderAndShadowTemplate.ts
│ │ │ ├── RoundedWithBorderTemplate.ts
│ │ │ ├── RoundedWithShadowTemplate.ts
│ │ │ └── ShadowTemplate.ts
│ │ ├── utils.ts
│ │ └── webgl
│ │ │ ├── Border.ts
│ │ │ ├── Default.ts
│ │ │ ├── DefaultBatched.ts
│ │ │ ├── HolePunch.ts
│ │ │ ├── LinearGradient.ts
│ │ │ ├── RadialGradient.ts
│ │ │ ├── Rounded.ts
│ │ │ ├── RoundedWithBorder.ts
│ │ │ ├── RoundedWithBorderAndShadow.ts
│ │ │ ├── RoundedWithShadow.ts
│ │ │ ├── SdfShader.ts
│ │ │ └── Shadow.ts
│ ├── text-rendering
│ │ ├── TextRenderingUtils.ts
│ │ ├── TextTextureRendererUtils.ts
│ │ ├── TrFontManager.ts
│ │ ├── font-face-types
│ │ │ ├── SdfTrFontFace
│ │ │ │ ├── SdfTrFontFace.ts
│ │ │ │ └── internal
│ │ │ │ │ ├── FontShaper.ts
│ │ │ │ │ ├── SdfFontShaper.test.ts
│ │ │ │ │ └── SdfFontShaper.ts
│ │ │ ├── TrFontFace.ts
│ │ │ ├── WebTrFontFace.ts
│ │ │ └── utils.ts
│ │ └── renderers
│ │ │ ├── CanvasTextRenderer.ts
│ │ │ ├── LightningTextTextureRenderer.ts
│ │ │ ├── SdfTextRenderer
│ │ │ ├── SdfTextRenderer.ts
│ │ │ └── internal
│ │ │ │ ├── PeekableGenerator.test.ts
│ │ │ │ ├── PeekableGenerator.ts
│ │ │ │ ├── SpecialCodepoints.ts
│ │ │ │ ├── constants.ts
│ │ │ │ ├── getStartConditions.ts
│ │ │ │ ├── getUnicodeCodepoints.test.ts
│ │ │ │ ├── getUnicodeCodepoints.ts
│ │ │ │ ├── layoutText.ts
│ │ │ │ ├── measureText.test.ts
│ │ │ │ ├── measureText.ts
│ │ │ │ ├── setRenderWindow.test.ts
│ │ │ │ ├── setRenderWindow.ts
│ │ │ │ └── util.ts
│ │ │ └── TextRenderer.ts
│ ├── textures
│ │ ├── ColorTexture.ts
│ │ ├── ImageTexture.ts
│ │ ├── NoiseTexture.ts
│ │ ├── RenderTexture.ts
│ │ ├── SubTexture.ts
│ │ └── Texture.ts
│ └── utils.ts
├── env.d.ts
├── main-api
│ ├── INode.ts
│ ├── Inspector.ts
│ ├── Renderer.ts
│ └── utils.ts
└── utils.ts
├── test
└── mockdata
│ └── Ubuntu-Bold.msdf.json
├── tsconfig.cfg.json
├── tsconfig.dist.json
├── tsconfig.json
├── tsconfig.vitest.json
├── typedoc.config.cjs
├── visual-regression
├── .npmrc
├── DOCKER.md
├── README.md
├── certified-snapshots
│ └── chromium-ci
│ │ ├── alignment-1.png
│ │ ├── alpha-1.png
│ │ ├── alpha-blending-1.png
│ │ ├── alpha-blending-2.png
│ │ ├── animation-events_a1-1.png
│ │ ├── animation-events_a1-2.png
│ │ ├── animation-events_a1-3.png
│ │ ├── animation-events_a2-1.png
│ │ ├── animation-events_a2-2.png
│ │ ├── animation-events_a2-3.png
│ │ ├── animation-events_a3-1.png
│ │ ├── animation-events_a3-2.png
│ │ ├── clear-color-setting-1.png
│ │ ├── clear-color-setting-2.png
│ │ ├── clear-color-setting-3.png
│ │ ├── clipping-1.png
│ │ ├── clipping-2.png
│ │ ├── clipping-3.png
│ │ ├── clipping-mutations-1.png
│ │ ├── clipping-mutations-2.png
│ │ ├── clipping-mutations-3.png
│ │ ├── destroy-1.png
│ │ ├── destroy-2.png
│ │ ├── ds-effect-radial-progress-1.png
│ │ ├── dynamic-shader-1.png
│ │ ├── dynamic-shader-circle-border-radius-1.png
│ │ ├── hole-punch-effect-1.png
│ │ ├── quads-rendered-1.png
│ │ ├── quads-rendered-2.png
│ │ ├── render-settings-1.png
│ │ ├── render-settings-2.png
│ │ ├── render-settings-3.png
│ │ ├── render-settings-4.png
│ │ ├── render-settings-5.png
│ │ ├── render-settings-6.png
│ │ ├── resize-mode-1.png
│ │ ├── resize-mode-2.png
│ │ ├── resize-mode-3.png
│ │ ├── resize-mode-4.png
│ │ ├── rtt-dimension-1.png
│ │ ├── rtt-dimension-2.png
│ │ ├── rtt-dimension-3.png
│ │ ├── rtt-dimension-4.png
│ │ ├── rtt-dimension-5.png
│ │ ├── rtt-dimension-6.png
│ │ ├── rtt-spritemap-1.png
│ │ ├── scaling-1.png
│ │ ├── scaling-2.png
│ │ ├── scaling-3.png
│ │ ├── shader-animation_animation1-1.png
│ │ ├── shader-animation_animation2-1.png
│ │ ├── shader-animation_startup-1.png
│ │ ├── shader-border-1.png
│ │ ├── shader-hole-punch-1.png
│ │ ├── shader-linear-gradient-1.png
│ │ ├── shader-radial-gradient-1.png
│ │ ├── shader-rounded-1.png
│ │ ├── shader-shadow-1.png
│ │ ├── text-align-1.png
│ │ ├── text-align-2.png
│ │ ├── text-align-3.png
│ │ ├── text-align-4.png
│ │ ├── text-align-5.png
│ │ ├── text-align-6.png
│ │ ├── text-alpha-1.png
│ │ ├── text-alpha-2.png
│ │ ├── text-baseline-1.png
│ │ ├── text-canvas-font-no-metrics-1.png
│ │ ├── text-canvas-font-no-metrics-2.png
│ │ ├── text-contain-1.png
│ │ ├── text-contain-10.png
│ │ ├── text-contain-2.png
│ │ ├── text-contain-3.png
│ │ ├── text-contain-4.png
│ │ ├── text-contain-5.png
│ │ ├── text-contain-6.png
│ │ ├── text-contain-7.png
│ │ ├── text-contain-8.png
│ │ ├── text-contain-9.png
│ │ ├── text-dimensions-1.png
│ │ ├── text-dimensions-2.png
│ │ ├── text-dimensions-3.png
│ │ ├── text-dimensions-4.png
│ │ ├── text-dimensions-5.png
│ │ ├── text-dimensions-6.png
│ │ ├── text-dimensions-7.png
│ │ ├── text-layout-consistency-1.png
│ │ ├── text-layout-consistency-2.png
│ │ ├── text-layout-consistency-3.png
│ │ ├── text-layout-consistency-modified-metrics-1.png
│ │ ├── text-layout-consistency-modified-metrics-2.png
│ │ ├── text-layout-consistency-modified-metrics-3.png
│ │ ├── text-line-height-1.png
│ │ ├── text-max-lines-1.png
│ │ ├── text-max-lines-2.png
│ │ ├── text-mixed-1.png
│ │ ├── text-offscreen-move-1.png
│ │ ├── text-offscreen-move-2.png
│ │ ├── text-offscreen-move-3.png
│ │ ├── text-offscreen-move-4.png
│ │ ├── text-offscreen-move-5.png
│ │ ├── text-offscreen-move-6.png
│ │ ├── text-overflow-suffix-1.png
│ │ ├── text-rotation-1.png
│ │ ├── text-rotation-2.png
│ │ ├── text-scaling-1.png
│ │ ├── text-scaling-2.png
│ │ ├── text-scaling-3.png
│ │ ├── text-scaling-4.png
│ │ ├── text-scaling-5.png
│ │ ├── text-scaling-6.png
│ │ ├── text-ssdf-1.png
│ │ ├── text-vertical-align-1.png
│ │ ├── text-vertical-align-2.png
│ │ ├── text-wordbreak-1.png
│ │ ├── text-wordbreak-2.png
│ │ ├── text-wordbreak-3.png
│ │ ├── text-wordbreak-4.png
│ │ ├── text-zwsp-1.png
│ │ ├── text-zwsp-2.png
│ │ ├── text-zwsp-3.png
│ │ ├── texture-autosize-1.png
│ │ ├── texture-base64-1.png
│ │ ├── texture-factory-1.png
│ │ ├── texture-source-1.png
│ │ ├── texture-spritemap-1.png
│ │ ├── texture-svg-1.png
│ │ ├── textures-1.png
│ │ ├── viewport-boundsmargin-1.png
│ │ ├── viewport-boundsmargin-10.png
│ │ ├── viewport-boundsmargin-11.png
│ │ ├── viewport-boundsmargin-12.png
│ │ ├── viewport-boundsmargin-2.png
│ │ ├── viewport-boundsmargin-3.png
│ │ ├── viewport-boundsmargin-4.png
│ │ ├── viewport-boundsmargin-5.png
│ │ ├── viewport-boundsmargin-6.png
│ │ ├── viewport-boundsmargin-7.png
│ │ ├── viewport-boundsmargin-8.png
│ │ ├── viewport-boundsmargin-9.png
│ │ ├── viewport-events-1.png
│ │ ├── viewport-events-10.png
│ │ ├── viewport-events-11.png
│ │ ├── viewport-events-12.png
│ │ ├── viewport-events-13.png
│ │ ├── viewport-events-14.png
│ │ ├── viewport-events-15.png
│ │ ├── viewport-events-16.png
│ │ ├── viewport-events-17.png
│ │ ├── viewport-events-18.png
│ │ ├── viewport-events-2.png
│ │ ├── viewport-events-3.png
│ │ ├── viewport-events-4.png
│ │ ├── viewport-events-5.png
│ │ ├── viewport-events-6.png
│ │ ├── viewport-events-7.png
│ │ ├── viewport-events-8.png
│ │ ├── viewport-events-9.png
│ │ ├── viewport-largebound-1.png
│ │ ├── viewport-largebound-2.png
│ │ ├── viewport-largebound-3.png
│ │ ├── viewport-strictbounds-1.png
│ │ ├── viewport-strictbounds-2.png
│ │ ├── viewport-strictbounds-3.png
│ │ └── zIndex-1.png
├── package.json
├── src
│ ├── build-docker.ts
│ ├── detectDockerRuntime.ts
│ ├── index.ts
│ └── snapshot.ts
└── tsconfig.json
└── vitest.config.ts
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | insert_final_newline = true
6 | end_of_line = lf
7 | indent_style = space
8 | indent_size = 2
9 | max_line_length = 80
10 | trim_trailing_whitespace = true
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml:
--------------------------------------------------------------------------------
1 | name: "💡 Feature Request"
2 | description: Create a new ticket for a new feature request
3 | title: "💡 [REQUEST] -
"
4 | labels: [
5 | "question"
6 | ]
7 | body:
8 | - type: textarea
9 | id: implementation_pr
10 | attributes:
11 | label: "Implementation PR"
12 | description: Pull request used
13 | placeholder: "#Pull Request ID"
14 | validations:
15 | required: false
16 | - type: textarea
17 | id: reference_issues
18 | attributes:
19 | label: "Reference Issues"
20 | description: Common issues
21 | placeholder: "#Issues IDs"
22 | validations:
23 | required: false
24 | - type: textarea
25 | id: summary
26 | attributes:
27 | label: "Summary"
28 | description: Provide a brief explanation of the feature
29 | placeholder: Describe in a few lines your feature request
30 | validations:
31 | required: true
32 | - type: textarea
33 | id: basic_example
34 | attributes:
35 | label: "Basic Example"
36 | description: Indicate here some basic examples of your feature.
37 | placeholder: A few specific words about your feature request.
38 | validations:
39 | required: true
40 | - type: textarea
41 | id: drawbacks
42 | attributes:
43 | label: "Drawbacks"
44 | description: What are the drawbacks/impacts of your feature request ?
45 | placeholder: Identify the drawbacks and impacts while being neutral on your feature request
46 | validations:
47 | required: true
48 | - type: textarea
49 | id: unresolved_question
50 | attributes:
51 | label: "Unresolved questions"
52 | description: What questions still remain unresolved ?
53 | placeholder: Identify any unresolved issues.
54 | validations:
55 | required: false
56 |
--------------------------------------------------------------------------------
/.github/workflows/examples.yml:
--------------------------------------------------------------------------------
1 | name: Deploy Examples
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | workflow_dispatch:
8 |
9 | permissions:
10 | contents: read
11 | pages: write
12 | id-token: write
13 |
14 | concurrency:
15 | group: "pages"
16 | cancel-in-progress: false
17 |
18 | jobs:
19 | deploy:
20 | environment:
21 | name: github-pages
22 | url: ${{ steps.deployment.outputs.page_url }}
23 | runs-on: ubuntu-latest
24 | steps:
25 | - name: Checkout
26 | uses: actions/checkout@v4
27 |
28 | - name: Install Node.js
29 | uses: actions/setup-node@v3
30 | with:
31 | node-version: 20
32 |
33 | - uses: pnpm/action-setup@v4
34 | name: Install pnpm
35 | with:
36 | run_install: false
37 |
38 | - name: Get pnpm store directory
39 | shell: bash
40 | run: |
41 | echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
42 |
43 | - uses: actions/cache@v3
44 | name: Setup pnpm cache
45 | with:
46 | path: ${{ env.STORE_PATH }}
47 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
48 | restore-keys: |
49 | ${{ runner.os }}-pnpm-store-
50 |
51 | - name: Install dependencies
52 | run: pnpm install
53 |
54 | - name: Build renderer
55 | run: pnpm build
56 |
57 | - name: Build examples
58 | run: cd examples && pnpm build
59 |
60 | - name: Setup Pages
61 | uses: actions/configure-pages@v5
62 |
63 | - name: Upload artifact
64 | uses: actions/upload-pages-artifact@v3
65 | with:
66 | path: './examples/dist'
67 |
68 | - name: Deploy to GitHub Pages
69 | id: deployment
70 | uses: actions/deploy-pages@v4
71 |
--------------------------------------------------------------------------------
/.github/workflows/inactive.yaml:
--------------------------------------------------------------------------------
1 | name: Close inactive issues
2 | on:
3 | schedule:
4 | - cron: "30 1 * * *"
5 |
6 | jobs:
7 | close-issues:
8 | runs-on: ubuntu-latest
9 | permissions:
10 | issues: write
11 | pull-requests: write
12 | steps:
13 | - uses: actions/stale@v9
14 | with:
15 | days-before-issue-stale: 180
16 | days-before-issue-close: 7
17 | stale-issue-label: "stale"
18 | stale-issue-message: "This issue is stale because it has been open for 180 days with no activity. It will be closed in 7 days if no further activity occurs."
19 | close-issue-message: "This issue was closed because it has been inactive for 7 days since being marked as stale."
20 | days-before-pr-stale: 180
21 | days-before-pr-close: 7
22 | stale-pr-message: "This pull request is stale because it has been open for 180 days with no activity. It will be closed in 7 days if no further activity occurs."
23 | close-pr-message: "This pull request was closed because it has been inactive for 7 days since being marked as stale."
24 | repo-token: ${{ secrets.GITHUB_TOKEN }}
25 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | on:
2 | pull_request:
3 | merge_group:
4 | types: [checks_requested]
5 | jobs:
6 | run-all-tests:
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - name: Checkout
11 | uses: actions/checkout@v3
12 |
13 | - name: Install Node.js
14 | uses: actions/setup-node@v3
15 | with:
16 | node-version: 20
17 |
18 | - uses: pnpm/action-setup@v4
19 | name: Install pnpm
20 | with:
21 | run_install: false
22 |
23 | - name: Get pnpm store directory
24 | shell: bash
25 | run: |
26 | echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
27 |
28 | - uses: actions/cache@v3
29 | name: Setup pnpm cache
30 | with:
31 | path: ${{ env.STORE_PATH }}
32 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
33 | restore-keys: |
34 | ${{ runner.os }}-pnpm-store-
35 |
36 | - name: Install dependencies
37 | run: pnpm install
38 |
39 | - name: Run Unit Tests
40 | run: pnpm test
41 |
42 | - name: Install Playwright Browser
43 | run: cd visual-regression && pnpm exec playwright install chromium
44 |
45 | - name: Run Visual Regression Tests
46 | run: pnpm run test:visual --color
47 | env:
48 | RUNTIME_ENV: ci
49 |
50 | - name: Upload failed-results as artifact
51 | if: ${{ failure() }}
52 | uses: actions/upload-artifact@v4
53 | with:
54 | name: failed-results
55 | path: visual-regression/failed-results/
56 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_store
3 | .idea
4 | typedocs
5 | dist
6 | dist-*
7 | examples/dist-tsc
8 | visual-regression/failed-results
9 | visual-regression/certified-snapshots/*-local
10 | build
11 | releases
12 | .tmp
13 | .env
14 | *.tgz
15 | .pnpm-store
16 | # This project uses `pnpm` for package management
17 | package-lock.json
18 | .vscode/launch.json
19 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | # If files exist in the `visual-regression/failed-results` directory, fail the commit
5 | if [ -n "$(ls -A visual-regression/failed-results)" ]; then
6 | echo "Failed Visual Regression Test results found in \`visual-regression/failed-results\`. Please fix them before committing."
7 | exit 1
8 | fi
9 |
10 | pnpm exec lint-staged
11 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict = true
2 | use-node-version = 20.9.0
3 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_store
3 | .idea
4 | dist
5 | build
6 | releases
7 | .tmp
8 | .env
9 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "all",
3 | "singleQuote": true
4 | }
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "editorconfig.editorconfig",
4 | "dbaeumer.vscode-eslint",
5 | "esbenp.prettier-vscode"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": false,
3 | "editor.defaultFormatter": "esbenp.prettier-vscode",
4 | "editor.codeActionsOnSave": [
5 | "source.formatDocument",
6 | "source.fixAll.eslint"
7 | ],
8 | "[typescript]": {
9 | "editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
10 | },
11 | }
12 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | If you would like to contribute code to this project you can do so through GitHub by forking the repository
4 | and sending a pull request.
5 | Before RDK accepts your code into the project you must sign the RDK Contributor License Agreement (CLA).
6 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | LICENSE
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use Playwright's base image
2 | FROM mcr.microsoft.com/playwright:v1.49.0-jammy
3 |
4 | # Set the working directory
5 | WORKDIR /work
6 |
7 | # Copy the necessary files to the container
8 | COPY .npmrc .npmrc
9 | COPY package.json package.json
10 |
11 | # Install PNPM
12 | RUN corepack enable && corepack prepare pnpm@8.15.5 --activate
13 |
14 | # Get pnpm to install the version of Node declared in .npmrc
15 | RUN pnpm exec ls
16 |
17 | # Set the entry point command
18 | CMD ["/bin/bash", "-c", "echo 'Must run with Visual Regression Test Runner: `pnpm run test:visual --ci`'"]
19 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | This component contains software that is Copyright 2023 Comcast Cable Communications Management, LLC.
2 | The component is licensed to you under the Apache License, Version 2.0 (the "License").
3 | You may not use the component except in compliance with the License.
4 |
--------------------------------------------------------------------------------
/RELEASE.md:
--------------------------------------------------------------------------------
1 | # Release Procedure
2 |
3 | Publish a new release with the below instructions, you must first be a contributor
4 | who is authorized to both push directly to this repo and publish packages to the
5 | lightningjs NPM scope.
6 |
7 | ## Mark, push and publish the release
8 |
9 | ```
10 | # Make sure you're on the main branch
11 | git checkout main
12 |
13 | # Stash any untracked + uncomitted changes
14 | git stash -u
15 |
16 | # Pull any new commits from GitHub
17 | git pull
18 |
19 | # Run the unit tests
20 | pnpm test
21 |
22 | # Run the Visual Regression Tests in CI mode
23 | pnpm test:visual --ci
24 |
25 | # Review changes in order to decide which release-increment to use
26 | git log --first-parent main...v
27 |
28 | # Mark the version update
29 | # This creates a new tagged commit for the version
30 | pnpm version # patch/minor/major
31 |
32 | # Publish the package to NPM
33 | pnpm publish --access public
34 |
35 | # Push version commit to github
36 | git push
37 |
38 | # Push version tag to github
39 | git push origin vX.X.X
40 |
41 | # Pop the stash (if one was created)
42 | git stash pop
43 | ```
44 |
45 | ## Generate a release on GitHub
46 |
47 | 1. Go to https://github.com/lightning-js/renderer/releases/new
48 | 2. Choose a Tag: _Choose the newly pushed tag_
49 | 3. Target: _main_
50 | 4. Name the release with the same name as the tag: vX.X.X
51 | 5. Click "Generate release notes"
52 | 6. Edit the release notes as appropriate:
53 | - User facing changes should go under the main "What's Changed" heading
54 | - Mark all breaking changes with: :warning: **Breaking Change:** (Description)
55 | - Move any changes specific to performance to a new level 3 heading called: **Performance**
56 | - If there are other non-user facing changes move them to a new level 3 heading called: **Non-User Facing**.
57 | 7. Set as the latest release: _Check_
58 | 8. Click "Publish release"
59 |
--------------------------------------------------------------------------------
/docs/CustomShaderEffectTexture.md:
--------------------------------------------------------------------------------
1 | # Custom Shaders / Effects / Textures
2 |
3 | For some examples on how to create custom shaders, effects and textures, see
4 | the (custom-shader-effect-texture)[./example-projects/custom-shader-effect-texture]
5 | example project.
6 |
--------------------------------------------------------------------------------
/docs/ManualRegressionTests.md:
--------------------------------------------------------------------------------
1 | # Manual Regression Tests
2 |
3 | In addition to the automated [Visual Regression Tests](../visual-regression/README.md),
4 | there are some tests that should be run manually on embedded devices to ensure
5 | the Renderer is working properly.
6 |
7 | ## Critical Texture Memory Cleanup Test
8 |
9 | `?test=texture-cleanup-critical&monitor=true`
10 |
11 | This test confirms the Renderer's ability to clean up textures when it never
12 | has a chance to perform Idle Texture Cleanups.
13 |
14 | Within an infinite loop, the test updates the texture of a single full screen
15 | background node to a new random NoiseTexture in rapid succession.
16 |
17 | **Expected Results**: The tests runs for at least 30 mins minutes without
18 | crashing or the visible Nodes becoming black. The Memory Monitor shows loaded
19 | textures reaching the Critical Threshold and then falling back to the target.
20 |
21 | To further confirm that the textures are being properly disposed of, you can use
22 | the Chrome Task Manager to monitor the GPU's memory usage:
23 |
24 | 1. Click Window > Task Manager
25 | 2. Locate the "GPU Process"
26 | 3. Observe the "Memory Footprint" column
27 | 4. Like the Memory Monitor, the value should increase, and fall significantly
28 | repeatedly.
29 |
30 | ## Idle Texture Memory Cleanup Test
31 |
32 | `?test=texture-cleanup-idle&monitor=true`
33 |
34 | This test confirms the Renderer's ability to clean up textures that are no longer
35 | renderable (not in the configured `boundsMargin`) from GPU VRAM when the Renderer
36 | becomes idle.
37 |
38 | Within an infinite loop, this test generates a grid of Nodes with random NoiseTextures
39 | assigned first completely visible on screen (for at least a frame) and then moves
40 | them outside of the configured `boundsMargin` before repeating the loop.
41 |
42 | **Expected Results**: The tests runs for at least 30 mins minutes without
43 | crashing or the visible Nodes becoming black. The Memory Monitor shows loaded
44 | textures falling to the Target Threshold roughly every 5 seconds.
45 |
46 | To further test that the textures are being properly disposed of, you can use the Chrome Task Manager to monitor the GPU's memory usage:
47 |
48 | 1. Click Window > Task Manager
49 | 2. Locate the "GPU Process"
50 | 3. Observe the "Memory Footprint" column
51 | 4. Like the Memory Monitor, the value should increase, and fall significantly
52 | repeatedly.
53 |
--------------------------------------------------------------------------------
/docs/NodeDependencyGraph.md:
--------------------------------------------------------------------------------
1 | # Node Depenedency Graph
2 |
3 | The diagram below describes the reactive flow of inputs into cached calculated data elements that are updated during each `update()` of a Core Node.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/docs/example-projects/custom-shader-effect-texture/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Renderer Browser Test
4 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/docs/example-projects/custom-shader-effect-texture/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "renderer-custom-shader",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "start": "vite --open --host",
9 | "build": "tsc && vite build",
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "dependencies": {
16 | "@lightningjs/renderer": "link:../../.."
17 | },
18 | "devDependencies": {
19 | "@types/node": "^20.12.12",
20 | "typescript": "^5.4.5",
21 | "vite": "^5.2.11"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/docs/example-projects/custom-shader-effect-texture/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/docs/example-projects/custom-shader-effect-texture/pnpm-workspace.yaml
--------------------------------------------------------------------------------
/docs/example-projects/custom-shader-effect-texture/src/assets/robot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/docs/example-projects/custom-shader-effect-texture/src/assets/robot.png
--------------------------------------------------------------------------------
/docs/example-projects/custom-shader-effect-texture/src/index.ts:
--------------------------------------------------------------------------------
1 | import { RendererMain } from '@lightningjs/renderer';
2 | import {
3 | SdfTextRenderer,
4 | WebGlCoreRenderer,
5 | } from '@lightningjs/renderer/webgl';
6 | import { CanvasTextRenderer } from '@lightningjs/renderer/canvas';
7 | import { Inspector } from '@lightningjs/renderer/inspector';
8 | import { MyCustomShader } from './MyCustomShader.js';
9 | import { MyCustomTexture } from './MyCustomTexture.js';
10 | import robotImg from './assets/robot.png';
11 |
12 | (async () => {
13 | const renderer = new RendererMain(
14 | {
15 | appWidth: 1920,
16 | appHeight: 1080,
17 | boundsMargin: [100, 100, 100, 100],
18 | clearColor: 0x000000ff,
19 | fpsUpdateInterval: 1000,
20 | enableContextSpy: false,
21 | inspector: Inspector,
22 | renderEngine: WebGlCoreRenderer,
23 | fontEngines: [SdfTextRenderer, CanvasTextRenderer],
24 | },
25 | 'app',
26 | );
27 |
28 | renderer.stage.shManager.registerShaderType('MyCustomShader', MyCustomShader);
29 | renderer.stage.txManager.registerTextureType(
30 | 'MyCustomTexture',
31 | MyCustomTexture,
32 | );
33 |
34 | const distortedBot = renderer.createNode({
35 | width: 300,
36 | height: 300,
37 | src: robotImg,
38 | parent: renderer.root,
39 | shader: renderer.createShader('MyCustomShader', {
40 | normalized: true,
41 | topLeft: { x: 0.5, y: 0 },
42 | topRight: { x: 0.500001, y: 0 },
43 | bottomRight: { x: 1, y: 1 },
44 | bottomLeft: { x: 0, y: 1 },
45 | }),
46 | });
47 |
48 | const pacman = renderer.createNode({
49 | x: 600,
50 | width: 300,
51 | height: 300,
52 | texture: renderer.createTexture('MyCustomTexture', {
53 | percent: 5,
54 | width: 300,
55 | height: 300,
56 | }),
57 | parent: renderer.root,
58 | });
59 | })().catch(console.error);
60 |
--------------------------------------------------------------------------------
/docs/example-projects/custom-shader-effect-texture/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | ///
21 | // This enables Vite's import.meta augmentations and possibly other things?
22 |
--------------------------------------------------------------------------------
/docs/example-projects/custom-shader-effect-texture/tsconfig.cfg.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "dist-cfg",
4 | "types": ["@types/node"],
5 | "target": "ESNext",
6 | "module": "ESNext",
7 | "moduleResolution": "node",
8 | "composite": true,
9 | "resolveJsonModule": true,
10 | "allowJs": true,
11 | "esModuleInterop": true,
12 | },
13 | "files": [
14 | "./vite.config.ts",
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/docs/example-projects/custom-shader-effect-texture/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "rootDir": ".",
4 | "types": [],
5 | "lib": ["ES2022", "DOM"],
6 | "outDir": "dist-tsc",
7 | "target": "ES2022",
8 | "module": "Node16",
9 | "moduleResolution": "Node16",
10 | "sourceMap": true,
11 | "declaration": true,
12 | "experimentalDecorators": true,
13 |
14 | // Type Checking / Syntax Rules
15 | "strict": true,
16 | "noUncheckedIndexedAccess": true,
17 | "noImplicitOverride": true,
18 | "allowSyntheticDefaultImports": true,
19 | "resolveJsonModule": true,
20 | "verbatimModuleSyntax": true,
21 | "composite": true,
22 | },
23 | "include": [
24 | "./src/**/*.ts"
25 | ],
26 | "exclude": ["node_modules", "./**/*.test.ts"],
27 | "references": [
28 | {
29 | "path": "./tsconfig.cfg.json"
30 | }
31 | ],
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/docs/images/dependency-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/docs/images/dependency-graph.png
--------------------------------------------------------------------------------
/docs/images/dependency-graph.txt:
--------------------------------------------------------------------------------
1 | Source:
2 | https://lucid.app/lucidchart/f5c48c94-6096-44c5-bca2-97fe2b581095/edit?viewport_loc=-1167%2C-285%2C4800%2C2244%2Cm8WTkWxK2plY&invitationId=inv_44218a81-5bb9-4436-a5e6-5697c146e164
3 | https://lucid.app/publicSegments/view/a6dc7e53-0327-46c7-b351-895dc8034af2/image.png
4 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | import eslintPluginTs from '@typescript-eslint/eslint-plugin';
2 | import tsParser from '@typescript-eslint/parser';
3 |
4 | export default [
5 | {
6 | files: ['**/*.ts'],
7 | languageOptions: {
8 | parser: tsParser,
9 | parserOptions: {
10 | ecmaVersion: 2022,
11 | sourceType: 'module',
12 | project: [
13 | './tsconfig.json',
14 | './tsconfig.vitest.json',
15 | './tsconfig.cfg.json',
16 | './examples/tsconfig.json',
17 | './visual-regression/tsconfig.json',
18 | './performance/tsconfig.json',
19 | ],
20 | },
21 | },
22 | plugins: {
23 | '@typescript-eslint': eslintPluginTs,
24 | },
25 | rules: {
26 | ...eslintPluginTs.configs.recommended.rules,
27 | '@typescript-eslint/no-unsafe-argument': 'warn',
28 | '@typescript-eslint/no-unsafe-assignment': 'warn',
29 | '@typescript-eslint/no-unsafe-return': 'warn',
30 | '@typescript-eslint/no-unsafe-call': 'warn',
31 | '@typescript-eslint/no-non-null-assertion': 'warn',
32 | '@typescript-eslint/no-unsafe-member-access': 'warn',
33 | '@typescript-eslint/ban-ts-comment': 'warn',
34 | '@typescript-eslint/no-explicit-any': 'warn',
35 | '@typescript-eslint/no-unused-vars': 'warn',
36 | '@typescript-eslint/no-empty-object-type': 'warn',
37 | '@typescript-eslint/no-unused-expressions': 'warn',
38 | },
39 | },
40 | {
41 | ignores: [
42 | '**/dist/**',
43 | 'node_modules',
44 | '**config**.ts',
45 | '**/docs/**',
46 | 'dist-vitest',
47 | 'dist-cfg',
48 | ],
49 | },
50 | ];
51 |
--------------------------------------------------------------------------------
/examples/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict = true
2 |
--------------------------------------------------------------------------------
/examples/assets/elevator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/elevator.png
--------------------------------------------------------------------------------
/examples/assets/green-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/green-100.png
--------------------------------------------------------------------------------
/examples/assets/green-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/green-25.png
--------------------------------------------------------------------------------
/examples/assets/green-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/green-50.png
--------------------------------------------------------------------------------
/examples/assets/green-50.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/green-50.psd
--------------------------------------------------------------------------------
/examples/assets/lightning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/lightning.png
--------------------------------------------------------------------------------
/examples/assets/red-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/red-100.png
--------------------------------------------------------------------------------
/examples/assets/red-25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/red-25.png
--------------------------------------------------------------------------------
/examples/assets/red-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/red-50.png
--------------------------------------------------------------------------------
/examples/assets/robot/elevator-background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/robot/elevator-background.png
--------------------------------------------------------------------------------
/examples/assets/robot/elevator-door-bottom-top-floor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/robot/elevator-door-bottom-top-floor.png
--------------------------------------------------------------------------------
/examples/assets/robot/elevator-door-left-ground-floor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/robot/elevator-door-left-ground-floor.png
--------------------------------------------------------------------------------
/examples/assets/robot/elevator-door-right-ground-floor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/robot/elevator-door-right-ground-floor.png
--------------------------------------------------------------------------------
/examples/assets/robot/elevator-door-shadow-ground-floor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/robot/elevator-door-shadow-ground-floor.png
--------------------------------------------------------------------------------
/examples/assets/robot/elevator-door-top-top-floor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/robot/elevator-door-top-top-floor.png
--------------------------------------------------------------------------------
/examples/assets/robot/environment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/robot/environment.png
--------------------------------------------------------------------------------
/examples/assets/robot/robot-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/robot/robot-shadow.png
--------------------------------------------------------------------------------
/examples/assets/robot/robot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/robot/robot.png
--------------------------------------------------------------------------------
/examples/assets/rocko.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/rocko.png
--------------------------------------------------------------------------------
/examples/assets/spritemap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/spritemap.png
--------------------------------------------------------------------------------
/examples/assets/test-etc1.pvr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/test-etc1.pvr
--------------------------------------------------------------------------------
/examples/assets/test-s3tc.ktx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/test-s3tc.ktx
--------------------------------------------------------------------------------
/examples/assets/testscreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/testscreen.png
--------------------------------------------------------------------------------
/examples/assets/testscreen_rotated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/assets/testscreen_rotated.png
--------------------------------------------------------------------------------
/examples/common/Component.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { INode, INodeProps, RendererMain } from '@lightningjs/renderer';
21 |
22 | export class Component {
23 | readonly node: INode;
24 |
25 | constructor(readonly renderer: RendererMain, nodeProps: Partial) {
26 | this.node = renderer.createNode({
27 | ...nodeProps,
28 | });
29 | }
30 |
31 | get x() {
32 | return this.node.x;
33 | }
34 |
35 | set x(x: number) {
36 | this.node.x = x;
37 | }
38 |
39 | get y() {
40 | return this.node.y;
41 | }
42 |
43 | set y(y: number) {
44 | this.node.y = y;
45 | }
46 |
47 | get width() {
48 | return this.node.width;
49 | }
50 |
51 | set width(width: number) {
52 | this.node.width = width;
53 | }
54 |
55 | get height() {
56 | return this.node.height;
57 | }
58 |
59 | set height(height: number) {
60 | this.node.height = height;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/examples/common/LocalStorage.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | // Retreive state from local storage (if localStorage is available)
21 | // and set the state of the app accordingly.
22 | export function loadStorage(testName: string): Partial | null {
23 | if (typeof window.localStorage === 'undefined') {
24 | return null;
25 | }
26 | try {
27 | const serializedState = localStorage.getItem(`${testName}-state`);
28 | if (serializedState === null) {
29 | return null;
30 | }
31 | return JSON.parse(serializedState);
32 | } catch (err) {
33 | return null;
34 | }
35 | }
36 |
37 | // Save the state of the app to local storage (if localStorage is available).
38 | export function saveStorage(testName: string, state: Partial): void {
39 | if (typeof window.localStorage === 'undefined') {
40 | return;
41 | }
42 | try {
43 | const serializedState = JSON.stringify(state);
44 | localStorage.setItem(`${testName}-state`, serializedState);
45 | } catch (err) {
46 | // Ignore write errors.
47 | }
48 | }
49 |
50 | // Clear the state of the app from local storage (if localStorage is available).
51 | export function clearStorage(testName: string): void {
52 | if (typeof window.localStorage === 'undefined') {
53 | return;
54 | }
55 | try {
56 | localStorage.removeItem(`${testName}-state`);
57 | } catch (err) {
58 | // Ignore write errors.
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/examples/common/installShaders.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import { type Stage } from '@lightningjs/renderer';
19 |
20 | export async function installShaders(stage: Stage, renderMode: string) {
21 | let shaders;
22 | if (renderMode === 'webgl') {
23 | shaders = await import('@lightningjs/renderer/webgl/shaders');
24 | } else if (renderMode === 'canvas') {
25 | shaders = await import('@lightningjs/renderer/canvas/shaders');
26 | }
27 | stage.shManager.registerShaderType('Rounded', shaders.Rounded);
28 | stage.shManager.registerShaderType(
29 | 'RoundedWithBorder',
30 | shaders.RoundedWithBorder,
31 | );
32 | stage.shManager.registerShaderType(
33 | 'RoundedWithShadow',
34 | shaders.RoundedWithShadow,
35 | );
36 | stage.shManager.registerShaderType(
37 | 'RoundedWithBorderAndShadow',
38 | shaders.RoundedWithBorderAndShadow,
39 | );
40 | stage.shManager.registerShaderType('Border', shaders.Border);
41 | stage.shManager.registerShaderType('Shadow', shaders.Shadow);
42 | stage.shManager.registerShaderType('HolePunch', shaders.HolePunch);
43 | stage.shManager.registerShaderType('RadialGradient', shaders.RadialGradient);
44 | stage.shManager.registerShaderType('LinearGradient', shaders.LinearGradient);
45 | }
46 |
--------------------------------------------------------------------------------
/examples/common/setupMathRandom.ts:
--------------------------------------------------------------------------------
1 | export async function setupMathRandom() {
2 | const mt19937 = await import('@stdlib/random-base-mt19937');
3 |
4 | const factory = mt19937.factory || mt19937.default.factory;
5 | const rand = factory({ seed: 1234 });
6 | Math.random = function () {
7 | return rand() / rand.MAX;
8 | };
9 | console.log('Math.random overridden with mt19937');
10 | }
11 |
--------------------------------------------------------------------------------
/examples/common/utils.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type {
21 | Dimensions,
22 | NodeTextLoadedPayload,
23 | INode,
24 | ITextNode,
25 | } from '@lightningjs/renderer';
26 |
27 | export async function waitForLoadedDimensions(
28 | node: INode | ITextNode,
29 | ): Promise {
30 | return new Promise((resolve) => {
31 | node.once('loaded', (_node: INode, payload: NodeTextLoadedPayload) => {
32 | const { width, height } = payload.dimensions;
33 | resolve({
34 | width,
35 | height,
36 | });
37 | });
38 | });
39 | }
40 |
--------------------------------------------------------------------------------
/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Renderer Browser Test
4 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "examples",
3 | "version": "1.0.0",
4 | "description": "",
5 | "type": "module",
6 | "main": "index.js",
7 | "private": true,
8 | "scripts": {
9 | "start": "concurrently -c \"auto\" \"pnpm:watch:renderer\" \"pnpm:dev\"",
10 | "start:prod": "concurrently -c \"auto\" \"pnpm:watch:renderer\" \"pnpm:watch\" \"sleep 5 && pnpm preview\"",
11 | "dev": "vite --open --host",
12 | "build": "vite build",
13 | "watch": "vite build --watch",
14 | "watch-all": "concurrently -c \"auto\" \"pnpm:watch:renderer\" \"pnpm:watch\"",
15 | "preview": "vite preview --host --open",
16 | "preview:automation": "vite preview",
17 | "build:renderer": "cd .. && pnpm build",
18 | "watch:renderer": "cd .. && pnpm watch"
19 | },
20 | "author": "Frank Weindel",
21 | "license": "Apache-2.0",
22 | "dependencies": {
23 | "@lightningjs/renderer": "link:..",
24 | "@stdlib/random-base-mt19937": "^0.2.1"
25 | },
26 | "devDependencies": {
27 | "@vitejs/plugin-legacy": "^5.4.2",
28 | "vite": "^5.4.8",
29 | "whatwg-fetch": "^3.6.2"
30 | },
31 | "engines": {
32 | "npm": "please-use-pnpm"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/examples/public/fonts/NotoSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/public/fonts/NotoSans-Bold.ttf
--------------------------------------------------------------------------------
/examples/public/fonts/NotoSans-Regular.ssdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/public/fonts/NotoSans-Regular.ssdf.png
--------------------------------------------------------------------------------
/examples/public/fonts/NotoSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/public/fonts/NotoSans-Regular.ttf
--------------------------------------------------------------------------------
/examples/public/fonts/Ubuntu-Bold.msdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/public/fonts/Ubuntu-Bold.msdf.png
--------------------------------------------------------------------------------
/examples/public/fonts/Ubuntu-Bold.ssdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/public/fonts/Ubuntu-Bold.ssdf.png
--------------------------------------------------------------------------------
/examples/public/fonts/Ubuntu-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/public/fonts/Ubuntu-Bold.ttf
--------------------------------------------------------------------------------
/examples/public/fonts/Ubuntu-Regular.msdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/public/fonts/Ubuntu-Regular.msdf.png
--------------------------------------------------------------------------------
/examples/public/fonts/Ubuntu-Regular.ssdf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/public/fonts/Ubuntu-Regular.ssdf.png
--------------------------------------------------------------------------------
/examples/public/fonts/Ubuntu-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/examples/public/fonts/Ubuntu-Regular.ttf
--------------------------------------------------------------------------------
/examples/tests/alpha.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { ExampleSettings } from '../common/ExampleSettings.js';
21 |
22 | export async function automation(settings: ExampleSettings) {
23 | // Snapshot single page
24 | await test(settings);
25 | await settings.snapshot();
26 | }
27 |
28 | export default async function test({ renderer, testRoot }: ExampleSettings) {
29 | const parent = renderer.createNode({
30 | x: 200,
31 | y: 240,
32 | width: 500,
33 | height: 500,
34 | color: 0x000000ff,
35 | parent: testRoot,
36 | zIndex: 0,
37 | zIndexLocked: 1,
38 | alpha: 0.5,
39 | });
40 |
41 | const child = renderer.createNode({
42 | x: 800,
43 | y: 0,
44 | width: 500,
45 | height: 500,
46 | color: 0xff0000ff,
47 | parent,
48 | zIndex: 12,
49 | alpha: 1,
50 | });
51 |
52 | console.log('ready!');
53 | }
54 |
--------------------------------------------------------------------------------
/examples/tests/child-positioning.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { ExampleSettings } from '../common/ExampleSettings.js';
21 |
22 | export default async function ({ renderer, testRoot }: ExampleSettings) {
23 | const rand = (min: number, max: number) => {
24 | return Math.random() * (max - min) + min;
25 | };
26 |
27 | new Array(16).fill(0).forEach((el, idx) => {
28 | const pivot = Math.random();
29 |
30 | const node = renderer.createNode({
31 | x: (idx % 5) * 250 + 100,
32 | y: Math.floor(idx / 5) * 250 + 100,
33 | width: rand(50, 120),
34 | height: rand(50, 120),
35 | color: 0x0000ffaa,
36 | parent: testRoot,
37 | });
38 |
39 | const R1 = renderer.createNode({
40 | x: 10,
41 | y: 10,
42 | width: 20,
43 | height: 20,
44 | color: 0xffffffff,
45 | parent: node,
46 | scale: 1,
47 | });
48 |
49 | const R3 = renderer.createNode({
50 | x: 40,
51 | y: 40,
52 | width: 10,
53 | height: 10,
54 | color: 0xffffffff,
55 | parent: node,
56 | scale: 1,
57 | rotation: 0.5,
58 | });
59 |
60 | setTimeout(() => {
61 | // node.rotation = 0.9;
62 | node
63 | .animate(
64 | {
65 | rotation: Math.PI * 2,
66 | x: rand(-500, 1700),
67 | y: rand(-500, 900),
68 | scale: 2,
69 | },
70 | {
71 | duration: 4000,
72 | loop: true,
73 | easing: 'cubic-bezier(0.5, 0.5, 0.5, 0.5)',
74 | },
75 | )
76 | .start();
77 | }, 1400);
78 | });
79 | }
80 |
--------------------------------------------------------------------------------
/examples/tests/clipping-mutations.ts:
--------------------------------------------------------------------------------
1 | import type { ExampleSettings } from '../common/ExampleSettings.js';
2 | import robotImg from '../assets/robot/robot.png';
3 |
4 | export async function automation(settings: ExampleSettings) {
5 | const next = await test(settings);
6 | // i = 0
7 | await settings.snapshot();
8 | next();
9 | // i = 1
10 | await settings.snapshot();
11 | next();
12 | // i = 2
13 | await settings.snapshot();
14 | }
15 |
16 | /**
17 | * Tests that the clipping rect is updated correctly when a parent node with
18 | * clipping set is moved.
19 | *
20 | * Use the 'right arrow' key to move the clipping parent around.
21 | *
22 | * @param settings
23 | * @returns
24 | */
25 | export default async function test(settings: ExampleSettings) {
26 | const { renderer, testRoot } = settings;
27 |
28 | // Set a smaller snapshot area
29 | testRoot.width = 200;
30 | testRoot.height = 200;
31 | testRoot.color = 0xffffffff;
32 |
33 | const clippedContainer = renderer.createNode({
34 | x: 0,
35 | y: 0,
36 | width: testRoot.width / 2,
37 | height: testRoot.height / 2,
38 | parent: settings.testRoot,
39 | color: 0x00ffffff,
40 | clipping: true,
41 | });
42 |
43 | renderer.createNode({
44 | x: -testRoot.width / 4,
45 | y: -testRoot.height / 4,
46 | width: testRoot.width,
47 | height: testRoot.height,
48 | scale: 0.9,
49 | parent: clippedContainer,
50 | src: robotImg,
51 | });
52 |
53 | let i = 0;
54 | const MAX_I = 2;
55 | function next() {
56 | i++;
57 | if (i > MAX_I) {
58 | i = 0;
59 | }
60 | if (i === 0) {
61 | clippedContainer.x = 0;
62 | clippedContainer.y = 0;
63 | } else if (i === 1) {
64 | clippedContainer.x = testRoot.width / 4;
65 | } else if (i === 2) {
66 | clippedContainer.x = testRoot.width / 2;
67 | clippedContainer.y = testRoot.height / 2;
68 | }
69 | }
70 |
71 | window.addEventListener('keydown', (event) => {
72 | // When right arrow is pressed, call next
73 | if (event.key === 'ArrowRight') {
74 | next();
75 | }
76 | });
77 |
78 | return next;
79 | }
80 |
--------------------------------------------------------------------------------
/examples/tests/gradient.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { ExampleSettings } from '../common/ExampleSettings.js';
21 |
22 | export default async function ({ renderer, testRoot }: ExampleSettings) {
23 | const elements = [
24 | 'colorTl',
25 | 'colorTr',
26 | 'colorBl',
27 | 'colorBr',
28 | 'colorTop',
29 | 'colorBottom',
30 | 'colorLeft',
31 | 'colorRight',
32 | 'color',
33 | ];
34 |
35 | const nodes = elements.map((element, idx) => {
36 | return renderer.createNode({
37 | x: (idx % 4) * 300 + 100,
38 | y: Math.floor(idx / 4) * 300 + 100,
39 | width: 250,
40 | height: 250,
41 | color: 0x000000ff,
42 | [element]: 0xff0000ff,
43 | parent: testRoot,
44 | });
45 | });
46 |
47 | setTimeout(() => {
48 | nodes.forEach((node, idx) => {
49 | node
50 | .animate(
51 | {
52 | [elements[idx] ?? 'color']: 0x00ff00ff,
53 | },
54 | {
55 | duration: 1000,
56 | },
57 | )
58 | .start();
59 | });
60 | }, 2000);
61 | /*
62 | * End: Sprite Map Demo
63 | */
64 | console.log('ready!');
65 | }
66 |
--------------------------------------------------------------------------------
/examples/tests/no-rtt.ts:
--------------------------------------------------------------------------------
1 | import type { ExampleSettings } from '../common/ExampleSettings.js';
2 | import test from './alpha-blending.js';
3 | interface AnimationExampleSettings {
4 | duration: number;
5 | easing: string;
6 | delay: number;
7 | loop: boolean;
8 | stopMethod: 'reverse' | 'reset' | false;
9 | }
10 |
11 | const animationSettings: Partial = {
12 | duration: 14000,
13 | delay: 400,
14 | loop: true,
15 | stopMethod: 'reverse',
16 | easing: 'ease-in-out-back',
17 | };
18 |
19 | export default async function ({ renderer, testRoot }: ExampleSettings) {
20 | const node = renderer.createNode({
21 | x: 0,
22 | y: 0,
23 | width: 1920,
24 | height: 1080,
25 | color: 0x000000ff,
26 | parent: testRoot,
27 | });
28 | const clippingNode = renderer.createNode({
29 | x: 0,
30 | y: 0,
31 | width: 1920,
32 | height: 1080,
33 | parent: node,
34 | clipping: true,
35 | color: 0x00000000,
36 | });
37 |
38 | const rootRenderToTextureNode = renderer.createNode({
39 | x: 0,
40 | y: 0,
41 | width: 1920,
42 | height: 1080,
43 | parent: clippingNode,
44 | rtt: false,
45 | zIndex: 5,
46 | colorTop: 0xc0ffee00,
47 | colorBottom: 0xbada5500,
48 | });
49 |
50 | new Array(2000).fill(0).forEach((_, i) => {
51 | const image = i % 105;
52 | const a = renderer.createNode({
53 | parent: rootRenderToTextureNode,
54 | x: (i % 15) * 120 + 120,
55 | y: Math.floor(i / 15) * 120 + 150,
56 | width: 120,
57 | height: 120,
58 | scale: 0.85,
59 | // src: '../assets/rocko.png',
60 | src: `https://picsum.photos/id/${image + 30}/120/120`,
61 | });
62 |
63 | const animation = a.animate(
64 | {
65 | y: Math.floor(i / 15) * 120 - 5000,
66 | },
67 | animationSettings,
68 | );
69 |
70 | animation.start();
71 | });
72 | }
73 |
--------------------------------------------------------------------------------
/examples/tests/rtt-nested-clipping.ts:
--------------------------------------------------------------------------------
1 | import type { ExampleSettings } from '../common/ExampleSettings.js';
2 | import rocko from '../assets/rocko.png';
3 |
4 | export default async function test({ renderer, testRoot }: ExampleSettings) {
5 | const node = renderer.createNode({
6 | x: 0,
7 | y: 0,
8 | width: 1920,
9 | height: 1080,
10 | color: 0x000000ff,
11 | parent: testRoot,
12 | });
13 |
14 | // RTT Node 1
15 | const rttNode = renderer.createNode({
16 | x: 100,
17 | y: 200,
18 | width: 400,
19 | height: 400,
20 | parent: node,
21 | rtt: true,
22 | zIndex: 5,
23 | colorTop: 0xfff00fff,
24 | colorBottom: 0x00ffffff,
25 | });
26 |
27 | const rect = renderer.createNode({
28 | x: 0,
29 | y: 0,
30 | width: 300,
31 | height: 300,
32 | parent: rttNode,
33 | clipping: true,
34 | color: 0xff0000ff,
35 | });
36 |
37 | renderer.createTextNode({
38 | x: 0,
39 | y: 0,
40 | text: 'Render to texture',
41 | parent: rttNode,
42 | fontSize: 48,
43 | color: 0xffffffff,
44 | fontFamily: 'Ubuntu',
45 | });
46 |
47 | renderer.createNode({
48 | x: 50,
49 | y: 100,
50 | width: 600,
51 | height: 600,
52 | parent: rttNode,
53 | src: rocko,
54 | });
55 |
56 | window.addEventListener('keydown', (e) => {
57 | if (e.key === 's') {
58 | // rect.clipping = !rect.clipping;
59 | rect
60 | .animate(
61 | {
62 | x: 100, //going to render out of bounds as well
63 | },
64 | {
65 | duration: 3000,
66 | easing: 'ease-out',
67 | loop: true,
68 | stopMethod: 'reverse',
69 | },
70 | )
71 | .start();
72 | }
73 | });
74 |
75 | // Define the page function to configure different test scenarios
76 | }
77 |
--------------------------------------------------------------------------------
/examples/tests/rtt.ts:
--------------------------------------------------------------------------------
1 | import type { ExampleSettings } from '../common/ExampleSettings.js';
2 | import test from './alpha-blending.js';
3 | interface AnimationExampleSettings {
4 | duration: number;
5 | easing: string;
6 | delay: number;
7 | loop: boolean;
8 | stopMethod: 'reverse' | 'reset' | false;
9 | }
10 |
11 | const animationSettings: Partial = {
12 | duration: 14000,
13 | delay: 400,
14 | loop: true,
15 | stopMethod: 'reverse',
16 | easing: 'ease-in-out-back',
17 | };
18 |
19 | const randomColor = () => {
20 | const randomInt = Math.floor(Math.random() * Math.pow(2, 32));
21 | const hexString = randomInt.toString(16).padStart(8, '0');
22 | return parseInt(hexString, 16);
23 | };
24 |
25 | const degToRad = (deg: number) => {
26 | return (Math.PI / 180) * deg;
27 | };
28 |
29 | export default async function ({ renderer, testRoot }: ExampleSettings) {
30 | const node = renderer.createNode({
31 | x: 0,
32 | y: 0,
33 | width: 1920,
34 | height: 1080,
35 | color: 0x000000ff,
36 | parent: testRoot,
37 | });
38 |
39 | const rootRenderToTextureNode = renderer.createNode({
40 | x: 0,
41 | y: 0,
42 | width: 1920,
43 | height: 1080,
44 | parent: node,
45 | rtt: true,
46 | zIndex: 5,
47 | colorTop: 0xc0ffeeff,
48 | colorBottom: 0xbada55ff,
49 | });
50 |
51 | new Array(105).fill(0).forEach((_, i) => {
52 | const a = renderer.createNode({
53 | parent: rootRenderToTextureNode,
54 | x: (i % 15) * 120 + 120,
55 | y: Math.floor(i / 15) * 120 + 150,
56 | width: 120,
57 | height: 120,
58 | scale: 1,
59 | // src: '../assets/rocko.png',
60 | src: `https://picsum.photos/id/${i + 30}/120/120`,
61 | });
62 | });
63 |
64 | new Array(20).fill(0).forEach((_, i) => {
65 | const a = renderer.createNode({
66 | x: (i % 1) * 1920,
67 | y: Math.floor(i / 1) * 800,
68 | width: 1920,
69 | height: 1080,
70 | parent: testRoot,
71 | alpha: 1,
72 | color: 0xffffffff,
73 | // Copy source texture from rootRenderToTextureNode
74 | texture: rootRenderToTextureNode.texture,
75 | });
76 |
77 | const animation = a.animate(
78 | {
79 | y: Math.floor(i / 1) * 800 - 15000,
80 | },
81 | animationSettings,
82 | );
83 | animation.start();
84 | });
85 |
86 | setTimeout(() => {
87 | rootRenderToTextureNode.alpha = 0;
88 | }, 2000);
89 | }
90 |
--------------------------------------------------------------------------------
/examples/tests/shader-animation.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { ExampleSettings } from '../common/ExampleSettings.js';
21 |
22 | export async function automation(settings: ExampleSettings) {
23 | // Snapshot single page
24 | await test(settings);
25 | // await settings.snapshot();
26 | }
27 |
28 | export default async function test({
29 | renderer,
30 | testRoot,
31 | snapshot,
32 | }: ExampleSettings) {
33 | const degToRad = (deg: number) => {
34 | return (Math.PI / 180) * deg;
35 | };
36 |
37 | const nodeSize = {
38 | width: 300,
39 | height: 300,
40 | };
41 |
42 | const t1 = renderer.createNode({
43 | ...nodeSize,
44 | x: 90,
45 | y: 90,
46 | color: 0xff0000ff,
47 | shader: renderer.createShader('Rounded', {
48 | radius: 100,
49 | }),
50 | parent: testRoot,
51 | });
52 |
53 | const t1Radius = renderer.createTextNode({
54 | mountX: 1,
55 | x: testRoot.width - 90,
56 | y: 90,
57 | fontSize: 40,
58 | fontFamily: 'Ubuntu',
59 | text: 'radius: 100',
60 | parent: testRoot,
61 | color: 0xffffffff,
62 | });
63 |
64 | await snapshot({ name: 'startup' });
65 |
66 | const shaderAnimation = t1.animate(
67 | {
68 | x: 1140,
69 | shaderProps: {
70 | radius: 150,
71 | },
72 | },
73 | {
74 | duration: 500,
75 | },
76 | );
77 | // shaderAnimation.start();
78 | // await shaderAnimation.waitUntilStopped();
79 | // t1Radius.text = 'radius: ' + t1.shader.props!.radius.toString();
80 | // await snapshot({ name: 'animation1' });
81 | }
82 |
--------------------------------------------------------------------------------
/examples/tests/shader-hole-punch.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { ExampleSettings } from '../common/ExampleSettings.js';
19 |
20 | export async function automation(settings: ExampleSettings) {
21 | // Snapshot single page
22 | await test(settings);
23 | await settings.snapshot();
24 | }
25 |
26 | export default async function test({ renderer, testRoot }: ExampleSettings) {
27 | const RedRect = renderer.createNode({
28 | x: 20,
29 | y: 20,
30 | width: 600,
31 | height: 400,
32 | color: 0xff0000ff,
33 | shader: renderer.createShader('HolePunch'),
34 | parent: testRoot,
35 | });
36 |
37 | const RedRect2 = renderer.createNode({
38 | x: 720,
39 | y: 20,
40 | width: 600,
41 | height: 400,
42 | color: 0xff0000ff,
43 | shader: renderer.createShader('HolePunch', {
44 | x: 100,
45 | y: 100,
46 | width: 100,
47 | height: 100,
48 | radius: 10,
49 | }),
50 | parent: testRoot,
51 | });
52 |
53 | const GreenRect = renderer.createNode({
54 | x: 20,
55 | y: 520,
56 | width: 600,
57 | height: 400,
58 | color: 0x00ff00ff,
59 | shader: renderer.createShader('HolePunch', {
60 | x: 100,
61 | y: 100,
62 | width: 200,
63 | height: 150,
64 | radius: 10,
65 | }),
66 | parent: testRoot,
67 | });
68 |
69 | const GreenRect2 = renderer.createNode({
70 | x: 720,
71 | y: 520,
72 | width: 600,
73 | height: 400,
74 | color: 0x00ff00ff,
75 | shader: renderer.createShader('HolePunch', {
76 | x: 270,
77 | y: 200,
78 | width: 225,
79 | height: 150,
80 | radius: [50, 20, 30],
81 | }),
82 | parent: testRoot,
83 | });
84 | }
85 |
--------------------------------------------------------------------------------
/examples/tests/shader-shadow.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { ExampleSettings } from '../common/ExampleSettings.js';
19 |
20 | export async function automation(settings: ExampleSettings) {
21 | // Snapshot single page
22 | await test(settings);
23 | await settings.snapshot();
24 | }
25 |
26 | export default async function test({ renderer, testRoot }: ExampleSettings) {
27 | const node = renderer.createNode({
28 | x: 0,
29 | y: 0,
30 | width: 1920,
31 | height: 1080,
32 | color: 0xffffffff,
33 | parent: testRoot,
34 | });
35 |
36 | renderer.createNode({
37 | x: 300,
38 | y: 300,
39 | mount: 0.5,
40 | width: 250,
41 | height: 250,
42 | color: 0xff00ffff,
43 | shader: renderer.createShader('Shadow', {
44 | x: 50,
45 | spread: 50,
46 | blur: 100,
47 | }),
48 | parent: node,
49 | });
50 |
51 | renderer.createNode({
52 | x: 700,
53 | y: 300,
54 | mount: 0.5,
55 | width: 250,
56 | height: 250,
57 | color: 0xff00ffff,
58 | shader: renderer.createShader('RoundedWithShadow', {
59 | radius: 10,
60 | 'shadow-x': 50,
61 | 'shadow-spread': 50,
62 | 'shadow-blur': 100,
63 | }),
64 | parent: node,
65 | });
66 |
67 | renderer.createNode({
68 | x: 1100,
69 | y: 300,
70 | mount: 0.5,
71 | width: 250,
72 | height: 250,
73 | color: 0xff00ffff,
74 | shader: renderer.createShader('RoundedWithBorderAndShadow', {
75 | radius: 10,
76 | 'shadow-x': 50,
77 | 'shadow-spread': 50,
78 | 'shadow-blur': 100,
79 | 'border-width': 20,
80 | }),
81 | parent: node,
82 | });
83 | }
84 |
--------------------------------------------------------------------------------
/examples/tests/stress-images.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { ExampleSettings } from '../common/ExampleSettings.js';
19 |
20 | export default async function ({ renderer, testRoot }: ExampleSettings) {
21 | const screenWidth = 1920;
22 | const screenHeight = 1080;
23 | const totalImages = 1000;
24 |
25 | // Calculate the grid dimensions for square images
26 | const gridSize = Math.ceil(Math.sqrt(totalImages)); // Approximate grid size
27 | const imageSize = Math.floor(
28 | Math.min(screenWidth / gridSize, screenHeight / gridSize),
29 | ); // Square size
30 |
31 | // Create a root node for the grid
32 | const gridNode = renderer.createNode({
33 | x: 0,
34 | y: 0,
35 | width: screenWidth,
36 | height: screenHeight,
37 | parent: testRoot,
38 | });
39 |
40 | // Create and position images in the grid
41 | new Array(totalImages).fill(0).forEach((_, i) => {
42 | const x = (i % gridSize) * imageSize;
43 | const y = Math.floor(i / gridSize) * imageSize;
44 |
45 | renderer.createNode({
46 | parent: gridNode,
47 | x,
48 | y,
49 | width: imageSize,
50 | height: imageSize,
51 | src: `https://picsum.photos/id/${i}/${imageSize}/${imageSize}`, // Random images
52 | });
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/examples/tests/stress-textures.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { ExampleSettings } from '../common/ExampleSettings.js';
19 |
20 | export const Colors = {
21 | Black: 0x000000ff,
22 | Red: 0xff0000ff,
23 | Green: 0x00ff00ff,
24 | Blue: 0x0000ffff,
25 | Magenta: 0xff00ffff,
26 | Gray: 0x7f7f7fff,
27 | White: 0xffffffff,
28 | };
29 |
30 | export default async function ({ renderer, testRoot }: ExampleSettings) {
31 | const screenWidth = 1920;
32 | const screenHeight = 1080;
33 | const totalImages = 1000;
34 |
35 | // Calculate the grid dimensions for square images
36 | const gridSize = Math.ceil(Math.sqrt(totalImages)); // Approximate grid size
37 | const imageSize = Math.floor(
38 | Math.min(screenWidth / gridSize, screenHeight / gridSize),
39 | ); // Square size
40 |
41 | // Create a root node for the grid
42 | const gridNode = renderer.createNode({
43 | x: 0,
44 | y: 0,
45 | width: screenWidth,
46 | height: screenHeight,
47 | parent: testRoot,
48 | });
49 |
50 | // Create and position images in the grid
51 | new Array(totalImages).fill(0).forEach((_, i) => {
52 | const x = (i % gridSize) * imageSize;
53 | const y = Math.floor(i / gridSize) * imageSize;
54 |
55 | // pick a random color from Colors
56 | const clr =
57 | Object.values(Colors)[
58 | Math.floor(Math.random() * Object.keys(Colors).length)
59 | ];
60 |
61 | renderer.createNode({
62 | parent: gridNode,
63 | x,
64 | y,
65 | width: imageSize,
66 | height: imageSize,
67 | color: clr,
68 | });
69 | });
70 | }
71 |
--------------------------------------------------------------------------------
/examples/tests/text-ssdf.ts:
--------------------------------------------------------------------------------
1 | import type { ExampleSettings } from '../common/ExampleSettings.js';
2 |
3 | export async function automation(settings: ExampleSettings) {
4 | await test(settings);
5 | await settings.snapshot();
6 | }
7 |
8 | /**
9 | * Tests that Single-Channel Signed Distance Field (SSDF) fonts are rendered
10 | * correctly.
11 | *
12 | * Text that is thinner than the certified snapshot may indicate that the
13 | * SSDF font atlas texture was premultiplied before being uploaded to the GPU.
14 | *
15 | * @param settings
16 | * @returns
17 | */
18 | export default async function test(settings: ExampleSettings) {
19 | const { renderer, testRoot } = settings;
20 |
21 | // Set a smaller snapshot area
22 | testRoot.width = 200;
23 | testRoot.height = 200;
24 | testRoot.color = 0xffffffff;
25 |
26 | renderer.createTextNode({
27 | text: 'SSDF',
28 | color: 0x000000ff,
29 | fontFamily: 'Ubuntu-ssdf',
30 | parent: testRoot,
31 | fontSize: 80,
32 | lineHeight: 80 * 1.2,
33 | });
34 | }
35 |
--------------------------------------------------------------------------------
/examples/tests/texture-autosize.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { ExampleSettings } from '../common/ExampleSettings.js';
19 | import robotImg from '../assets/robot/robot.png';
20 | import { waitForLoadedDimensions } from '../common/utils.js';
21 |
22 | export async function automation(settings: ExampleSettings) {
23 | await test(settings);
24 | await settings.snapshot();
25 | }
26 |
27 | /**
28 | * Tests that text nodes with different contain settings and text renderers
29 | * are displayed correctly.
30 | *
31 | * Press the right arrow key to cycle through the different settings when
32 | * running in the browser.
33 | *
34 | * @param settings
35 | * @returns
36 | */
37 | export default async function test(settings: ExampleSettings) {
38 | const { renderer, testRoot } = settings;
39 |
40 | // Set a smaller snapshot area
41 | testRoot.width = 200;
42 | testRoot.height = 250;
43 | testRoot.color = 0xffffffff;
44 |
45 | const image = renderer.createNode({
46 | mount: 0.5,
47 | x: testRoot.width / 2,
48 | y: testRoot.height / 4,
49 | autosize: true,
50 | src: robotImg,
51 | parent: testRoot,
52 | });
53 |
54 | const dimensions = await waitForLoadedDimensions(image);
55 |
56 | const dimensionsMatch =
57 | dimensions.width === image.width && dimensions.height === image.height;
58 |
59 | renderer.createTextNode({
60 | mountX: 0.5,
61 | mountY: 1,
62 | x: testRoot.width / 2,
63 | y: testRoot.height,
64 | textAlign: 'center',
65 | text: dimensionsMatch ? 'Autosize\nSuccess' : 'Autosize\nFailure',
66 | color: dimensionsMatch ? 0x00ff00ff : 0xff0000ff,
67 | fontSize: 50,
68 | fontFamily: 'Ubuntu',
69 | parent: testRoot,
70 | });
71 | }
72 |
--------------------------------------------------------------------------------
/examples/tests/tx-compression.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { ExampleSettings } from '../common/ExampleSettings.js';
21 |
22 | export default async function ({ renderer, testRoot }: ExampleSettings) {
23 | renderer.createTextNode({
24 | x: 100,
25 | y: 100,
26 | color: 0xffffffff,
27 | alpha: 1.0,
28 | text: 'etc1 compression in .pvr',
29 | fontFamily: 'Ubuntu',
30 | fontSize: 30,
31 | parent: testRoot,
32 | });
33 |
34 | renderer.createNode({
35 | x: 100,
36 | y: 170,
37 | width: 550,
38 | height: 550,
39 | src: '../assets/test-etc1.pvr',
40 | parent: testRoot,
41 | });
42 |
43 | renderer.createTextNode({
44 | x: 800,
45 | y: 100,
46 | color: 0xffffffff,
47 | alpha: 1.0,
48 | text: 's3tc compression in .ktx',
49 | fontFamily: 'Ubuntu',
50 | fontSize: 30,
51 | parent: testRoot,
52 | });
53 |
54 | renderer.createNode({
55 | x: 800,
56 | y: 170,
57 | width: 400,
58 | height: 400,
59 | src: '../assets/test-s3tc.ktx',
60 | parent: testRoot,
61 | });
62 | }
63 |
--------------------------------------------------------------------------------
/examples/tests/viewport-strictbounds.ts:
--------------------------------------------------------------------------------
1 | import type { ExampleSettings } from '../common/ExampleSettings.js';
2 |
3 | export async function automation(settings: ExampleSettings) {
4 | const page = await test(settings);
5 | page(1);
6 | await settings.snapshot();
7 |
8 | page(2);
9 | await settings.snapshot();
10 |
11 | page(3);
12 | await settings.snapshot();
13 | }
14 |
15 | export default async function test({ renderer, testRoot }: ExampleSettings) {
16 | // Create a container node
17 | const containerNode = renderer.createNode({
18 | x: 10,
19 | y: 100,
20 | width: 1000,
21 | height: 600,
22 | color: 0xff0000ff, // Red
23 | parent: testRoot,
24 | strictBounds: false,
25 | });
26 |
27 | const status = renderer.createTextNode({
28 | text: 'Strict Bound: ',
29 | fontSize: 30,
30 | x: 10,
31 | y: 50,
32 | parent: testRoot,
33 | });
34 |
35 | const amountOfNodes = 11;
36 | const childNodeWidth = 1700 / amountOfNodes;
37 |
38 | // Create 11 child nodes
39 | for (let i = 0; i < amountOfNodes; i++) {
40 | const childNode = renderer.createNode({
41 | x: i * childNodeWidth + i * 100,
42 | y: 100,
43 | width: childNodeWidth,
44 | height: 300,
45 | color: 0x00ff00ff, // Green
46 | parent: containerNode,
47 | });
48 |
49 | const nodeTest = renderer.createTextNode({
50 | x: 10,
51 | y: 130,
52 | text: `Node ${i}`,
53 | color: 0x000000ff,
54 | parent: childNode,
55 | });
56 | }
57 |
58 | renderer.on('idle', () => {
59 | status.text = 'Strict Bound: ' + String(containerNode.strictBounds);
60 | });
61 |
62 | window.onkeydown = (e) => {
63 | if (e.key === 'ArrowRight') {
64 | containerNode.x -= 100;
65 | }
66 |
67 | if (e.key === 'ArrowLeft') {
68 | containerNode.x += 100;
69 | }
70 |
71 | if (e.key === ' ') {
72 | containerNode.strictBounds = !containerNode.strictBounds;
73 | }
74 | };
75 |
76 | const page = (i = 0) => {
77 | switch (i) {
78 | case 1:
79 | containerNode.x = -590;
80 | break;
81 |
82 | case 2:
83 | containerNode.x = -1390;
84 | break;
85 |
86 | case 3:
87 | containerNode.strictBounds = true;
88 | break;
89 | }
90 | };
91 |
92 | return page;
93 | }
94 |
--------------------------------------------------------------------------------
/examples/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "rootDir": ".",
5 | "outDir": "dist-tsc",
6 | "types": [],
7 | "lib": ["ES2022", "DOM"],
8 | "noEmit": true,
9 | },
10 | "include": [
11 | "./**/*.ts", "./common/**/*.ts"
12 | ],
13 | "exclude": ["node_modules", "./**/*.test.ts"],
14 | }
15 |
--------------------------------------------------------------------------------
/examples/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | ///
21 | // This enables Vite's import.meta augmentations and possibly other things?
22 |
--------------------------------------------------------------------------------
/exports/canvas-shaders.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | export * from '../src/core/renderers/canvas/CanvasShaderNode.js';
19 |
20 | export { Rounded } from '../src/core/shaders/canvas/Rounded.js';
21 | export { RoundedWithBorder } from '../src/core/shaders/canvas/RoundedWithBorder.js';
22 | export { RoundedWithBorderAndShadow } from '../src/core/shaders/canvas/RoundedWithBorderAndShadow.js';
23 | export { RoundedWithShadow } from '../src/core/shaders/canvas/RoundedWithShadow.js';
24 | export { Border } from '../src/core/shaders/canvas/Border.js';
25 | export { Shadow } from '../src/core/shaders/canvas/Shadow.js';
26 | export { HolePunch } from '../src/core/shaders/canvas/HolePunch.js';
27 | export { LinearGradient } from '../src/core/shaders/canvas/LinearGradient.js';
28 | export { RadialGradient } from '../src/core/shaders/canvas/RadialGradient.js';
29 |
--------------------------------------------------------------------------------
/exports/canvas.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | /**
20 | * Canvas Text Renderer
21 | *
22 | * @remarks
23 | * This module exports the Canvas Text Renderer for the Lightning 3 Renderer.
24 | * The Canvas Text Renderer is used to render text using the Canvas API,
25 | * this is slightly less performant than the SDF Text Renderer. However
26 | * the Canvas Text Renderer is more widely supported on older devices.
27 | *
28 | * You can import the exports from this module like so:
29 | * ```ts
30 | * import { CanvasTextRenderer } from '@lightning/renderer';
31 | * ```
32 | *
33 | * @module Canvas
34 | *
35 | * @packageDocumentation
36 | */
37 |
38 | export { CanvasTextRenderer } from '../src/core/text-rendering/renderers/CanvasTextRenderer.js';
39 | export { CanvasRenderer } from '../src/core/renderers/canvas/CanvasRenderer.js';
40 | export { CanvasTexture } from '../src/core/renderers/canvas/CanvasTexture.js';
41 | export * from '../src/core/renderers/canvas/CanvasShaderNode.js';
42 | /**
43 | * @deprecated Use CanvasRenderer.
44 | */
45 | export { CanvasRenderer as CanvasCoreRenderer } from '../src/core/renderers/canvas/CanvasRenderer.js';
46 |
--------------------------------------------------------------------------------
/exports/inspector.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | /**
21 | * @module Inspector
22 | */
23 |
24 | export { Inspector } from '../src/main-api/Inspector.js';
25 |
--------------------------------------------------------------------------------
/exports/utils.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | /**
20 | * Auxiliary Utilities
21 | *
22 | * @remarks
23 | * This module exports the a set of utilities that may be optionally used by
24 | * developers using the Lightning 3 Renderer.
25 | *
26 | * You can import the exports from this module like so:
27 | * ```ts
28 | * import { assertTruthy } from '@lightning/renderer';
29 | * ```
30 | *
31 | * @internalRemarks
32 | * Exports in here should be chosen wisely, as they will be exposed to
33 | * directly developers.
34 | *
35 | * They should be general utilities that are NOT directly coupled to the
36 | * Lightning Renderer, and not specific to any particular platform.
37 | *
38 | * @packageDocumentation
39 | *
40 | * @module Utils
41 | */
42 | export {
43 | assertTruthy,
44 | mergeColorAlpha,
45 | deg2Rad,
46 | mergeColorProgress,
47 | } from '../src/utils.js';
48 | export { getNormalizedRgbaComponents } from '../src/core/lib/utils.js';
49 | export { getTimingFunction } from '../src/core/utils.js';
50 | export { EventEmitter } from '../src/common/EventEmitter.js';
51 |
--------------------------------------------------------------------------------
/exports/webgl-shaders.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 | export * from '../src/core/renderers/webgl/WebGlShaderNode.js';
18 |
19 | export { Rounded } from '../src/core/shaders/webgl/Rounded.js';
20 | export { RoundedWithBorder } from '../src/core/shaders/webgl/RoundedWithBorder.js';
21 | export { RoundedWithBorderAndShadow } from '../src/core/shaders/webgl/RoundedWithBorderAndShadow.js';
22 | export { RoundedWithShadow } from '../src/core/shaders/webgl/RoundedWithShadow.js';
23 | export { Border } from '../src/core/shaders/webgl/Border.js';
24 | export { Shadow } from '../src/core/shaders/webgl/Shadow.js';
25 | export { HolePunch } from '../src/core/shaders/webgl/HolePunch.js';
26 | export { LinearGradient } from '../src/core/shaders/webgl/LinearGradient.js';
27 | export { RadialGradient } from '../src/core/shaders/webgl/RadialGradient.js';
28 | export { Default } from '../src/core/shaders/webgl/Default.js';
29 |
--------------------------------------------------------------------------------
/exports/webgl.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | /**
21 | * SDF Font renderer
22 | *
23 | * @remarks
24 | * This module exports the SDF Font renderer for the Lightning 3 Renderer.
25 | * The SDF Font renderer is used to render text using Single-Channel Signed
26 | * Distance Field (SSDF) fonts or Multi-Channel Signed Distance Field (MSDF)
27 | * fonts. The SDF font renderer is used to render text in a way that is
28 | * optimized for GPU rendering.
29 | *
30 | * You can import the exports from this module like so:
31 | * ```ts
32 | * import { SdfTextRenderer } from '@lightning/renderer';
33 | * ```
34 | *
35 | * @packageDocumentation
36 | */
37 |
38 | export { SdfTextRenderer } from '../src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js';
39 | export { WebGlRenderer } from '../src/core/renderers/webgl/WebGlRenderer.js';
40 | export { WebGlCtxTexture } from '../src/core/renderers/webgl/WebGlCtxTexture.js';
41 |
42 | export * from '../src/core/renderers/webgl/WebGlShaderNode.js';
43 |
44 | /**
45 | * @deprecated Use WebGlRenderer.
46 | */
47 | export { WebGlRenderer as WebGlCoreRenderer } from '../src/core/renderers/webgl/WebGlRenderer.js';
48 | export { WebGlRenderer as WebGlCoreCtxTexture } from '../src/core/renderers/webgl/WebGlRenderer.js';
49 |
50 | export * as shaders from './webgl-shaders.js';
51 |
--------------------------------------------------------------------------------
/performance/.gitignore:
--------------------------------------------------------------------------------
1 | baseline.json
2 |
--------------------------------------------------------------------------------
/performance/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/performance/bun.lockb
--------------------------------------------------------------------------------
/performance/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "performance",
3 | "version": "0.0.1",
4 | "author": "",
5 | "main": "index.js",
6 | "description": "",
7 | "keywords": [],
8 | "license": "ISC",
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "dependencies": {
13 | "sinon": "^18.0.0",
14 | "tinybench": "^2.9.0",
15 | "ts-sinon": "^2.0.2"
16 | },
17 | "devDependencies": {
18 | "@types/bun": "^1.1.8"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/performance/readme.md:
--------------------------------------------------------------------------------
1 | # Performance Benchmark Utility
2 |
3 | This utility allows you to run performance benchmarks for various components of the project. It provides a simple way to execute tests, compare results against a baseline, and create new baselines.
4 |
5 | ## Usage
6 |
7 | ### Running Tests
8 |
9 | To run all tests:
10 | `bun run performance/index.ts`
11 |
12 | To run a specific test:
13 | `bun run performance/index.ts -t `
14 |
15 | ### Creating a New Baseline
16 |
17 | To create a new baseline:
18 | `bun run performance/index.ts -c`
19 |
20 | Results are saved to `performance/baseline.json` and will be automatically used for future comparisons.
21 |
22 | ## Warning
23 |
24 | Use with care, these are limited benchmarks and highligh a specific case of the code, and should be used as approximations to see if changes have improved performance. Use them in combination with other tests such as rendering benchmarks to get a more complete picture.
25 |
26 | Don't tunnel on performance, and use these results as a tool to guide your development.
27 |
--------------------------------------------------------------------------------
/performance/src/WebGlContextWrapper.ts:
--------------------------------------------------------------------------------
1 | // Tree - mimic a rendering tree with core nodes and animations
2 | // test modules
3 | import { Bench } from 'tinybench';
4 | // import * as sinon from 'ts-sinon';
5 | import { performance } from 'perf_hooks';
6 | import { type IndividualTestResult } from './utils/types.js';
7 |
8 | import { compareArrays } from '../../src/core/lib/WebGlContextWrapper.js';
9 |
10 | const bench = new Bench();
11 |
12 | // Grab command line arguments
13 | const args = process.argv.slice(2);
14 | const isTestRunnerTest = args.includes('--testRunner');
15 |
16 | // generate large array with random values
17 | const largeArray = new Array(1000).fill(0).map(() => Math.random());
18 | const largeArrayCopy = largeArray.slice();
19 |
20 | // change random value in at middle index
21 | const middleIndex = Math.floor(largeArray.length / 2);
22 | largeArrayCopy[middleIndex] = Math.random();
23 |
24 | bench
25 | .add('Arrays', () => {
26 | compareArrays([1, 2, 3], [1, 2, 3]);
27 | })
28 | .add('Large Arrays', () => {
29 | compareArrays(new Array(1000).fill(1), new Array(1000).fill(1));
30 | })
31 | .add('Large Arrays diff vals', () => {
32 | compareArrays(new Array(1000).fill(1), new Array(1000).fill(2));
33 | })
34 | .add('Large Arrays diff lengths', () => {
35 | compareArrays(new Array(1000).fill(1), new Array(1001).fill(1));
36 | })
37 | .add('Large Array random diff', () => {
38 | compareArrays(largeArray, largeArrayCopy);
39 | });
40 |
41 | await bench.warmup();
42 | await bench.run();
43 |
44 | if (!isTestRunnerTest) {
45 | console.table(bench.table());
46 | }
47 |
48 | if (isTestRunnerTest) {
49 | const results: IndividualTestResult[] = [];
50 |
51 | bench.tasks.forEach((task) => {
52 | if (!task.result) {
53 | return;
54 | }
55 |
56 | if (task.result.error) {
57 | return;
58 | }
59 |
60 | results.push({
61 | name: task.name,
62 | opsPerSecond: task.result.hz,
63 | avgTime: task.result.mean * 1000 * 1000,
64 | margin: task.result.rme,
65 | samples: task.result.samples.length,
66 | });
67 | });
68 |
69 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
70 | // @ts-ignore
71 | process.send(results);
72 | }
73 |
--------------------------------------------------------------------------------
/performance/src/utils/types.ts:
--------------------------------------------------------------------------------
1 | export interface IndividualTestResult {
2 | name: string;
3 | opsPerSecond: number;
4 | avgTime: number;
5 | margin: number;
6 | samples: number;
7 | }
8 |
9 | export interface TestResult {
10 | name: string;
11 | results: IndividualTestResult[];
12 | }
13 |
--------------------------------------------------------------------------------
/performance/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "types": [],
5 | "lib": ["ES2022"],
6 | "module":"ESNext",
7 | "moduleResolution": "Node"
8 | },
9 | "include": [
10 | "./**/*.ts", "../src/**/*.ts"
11 | ],
12 | "exclude": ["node_modules", "./**/*.test.ts"],
13 | }
14 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2023 Comcast Cable Communications Management, LLC
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | #
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | #
8 | # Unless required by applicable law or agreed to in writing, software
9 | # distributed under the License is distributed on an "AS IS" BASIS,
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 | #
14 | # SPDX-License-Identifier: Apache-2.0
15 |
16 | packages:
17 | - "examples"
18 | - "visual-regression"
19 |
--------------------------------------------------------------------------------
/src/common/IEventEmitter.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | export interface IEventEmitter<
19 | T extends object = { [s: string]: (target: any, data: any) => void },
20 | > {
21 | on(event: Extract, listener: T[K]): void;
22 | once(event: Extract, listener: T[K]): void;
23 | off(event: Extract, listener: T[K]): void;
24 | emit(
25 | event: Extract,
26 | data: Parameters[1],
27 | ): void;
28 | }
29 |
--------------------------------------------------------------------------------
/src/core/animations/AnimationManager.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import { CoreAnimation } from './CoreAnimation.js';
21 |
22 | export class AnimationManager {
23 | activeAnimations: Set = new Set();
24 |
25 | registerAnimation(animation: CoreAnimation) {
26 | this.activeAnimations.add(animation);
27 | }
28 |
29 | unregisterAnimation(animation: CoreAnimation) {
30 | this.activeAnimations.delete(animation);
31 | }
32 |
33 | update(dt: number) {
34 | this.activeAnimations.forEach((animation) => {
35 | animation.update(dt);
36 | });
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/core/lib/ContextSpy.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | /**
21 | * Class that keeps track of the invocations of Context methods when
22 | * the `enableContextSpy` renderer option is enabled.
23 | */
24 | export class ContextSpy {
25 | private data: Record = {};
26 |
27 | reset() {
28 | this.data = {};
29 | }
30 |
31 | increment(name: string) {
32 | if (!this.data[name]) {
33 | this.data[name] = 0;
34 | }
35 | this.data[name]++;
36 | }
37 |
38 | getData() {
39 | return { ...this.data };
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/core/lib/RenderCoords.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 | export class RenderCoords {
18 | public x1: number;
19 | public y1: number;
20 | public x2: number;
21 | public y2: number;
22 | public x3: number;
23 | public y3: number;
24 | public x4: number;
25 | public y4: number;
26 |
27 | constructor(
28 | x1: number,
29 | y1: number,
30 | x2: number,
31 | y2: number,
32 | x3: number,
33 | y3: number,
34 | x4: number,
35 | y4: number,
36 | ) {
37 | this.x1 = x1;
38 | this.y1 = y1;
39 | this.x2 = x2;
40 | this.y2 = y2;
41 | this.x3 = x3;
42 | this.y3 = y3;
43 | this.x4 = x4;
44 | this.y4 = y4;
45 | }
46 |
47 | static translate(
48 | x1: number,
49 | y1: number,
50 | x2: number,
51 | y2: number,
52 | x3: number,
53 | y3: number,
54 | x4: number,
55 | y4: number,
56 | out?: RenderCoords,
57 | ): RenderCoords {
58 | if (out === undefined) {
59 | return new RenderCoords(x1, y1, x2, y2, x3, y3, x4, y4);
60 | }
61 | out.x1 = x1;
62 | out.y1 = y1;
63 | out.x2 = x2;
64 | out.y2 = y2;
65 | out.x3 = x3;
66 | out.y3 = y3;
67 | out.x4 = x4;
68 | out.y4 = y4;
69 | return out;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/core/lib/textureSvg.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import { assertTruthy } from '../../utils.js';
21 | import { type TextureData } from '../textures/Texture.js';
22 |
23 | /**
24 | * Tests if the given location is a SVG
25 | * @param url
26 | * @remarks
27 | * This function is used to determine if the given image url is a SVG
28 | * image
29 | * @returns
30 | */
31 | export function isSvgImage(url: string): boolean {
32 | return /\.(svg)(\?.*)?$/.test(url);
33 | }
34 |
35 | /**
36 | * Loads a SVG image
37 | * @param url
38 | * @returns
39 | */
40 | export const loadSvg = (
41 | url: string,
42 | width: number | null,
43 | height: number | null,
44 | sx: number | null,
45 | sy: number | null,
46 | sw: number | null,
47 | sh: number | null,
48 | ): Promise => {
49 | return new Promise((resolve, reject) => {
50 | const canvas = document.createElement('canvas');
51 | const ctx = canvas.getContext('2d');
52 | assertTruthy(ctx);
53 |
54 | ctx.imageSmoothingEnabled = true;
55 | const img = new Image();
56 | img.onload = () => {
57 | const x = sx ?? 0;
58 | const y = sy ?? 0;
59 | const w = width || img.width;
60 | const h = height || img.height;
61 |
62 | canvas.width = w;
63 | canvas.height = h;
64 | ctx.drawImage(img, 0, 0, w, h);
65 |
66 | resolve({
67 | data: ctx.getImageData(x, y, sw ?? w, sh ?? h),
68 | premultiplyAlpha: false,
69 | });
70 | };
71 |
72 | img.onerror = (err) => {
73 | reject(err);
74 | };
75 |
76 | img.src = url;
77 | });
78 | };
79 |
--------------------------------------------------------------------------------
/src/core/platforms/web/WebPlatform.ts:
--------------------------------------------------------------------------------
1 | import { Platform } from '../Platform.js';
2 | import type { Stage } from '../../Stage.js';
3 |
4 | export class WebPlatform extends Platform {
5 | ////////////////////////
6 | // Platform-specific methods
7 | ////////////////////////
8 |
9 | override createCanvas(): HTMLCanvasElement {
10 | const canvas = document.createElement('canvas');
11 | return canvas;
12 | }
13 |
14 | override getElementById(id: string): HTMLElement | null {
15 | return document.getElementById(id);
16 | }
17 |
18 | ////////////////////////
19 | // Update loop
20 | ////////////////////////
21 |
22 | override startLoop(stage: Stage): void {
23 | let isIdle = false;
24 | const runLoop = () => {
25 | stage.updateFrameTime();
26 | stage.updateAnimations();
27 |
28 | if (!stage.hasSceneUpdates()) {
29 | // We still need to calculate the fps else it looks like the app is frozen
30 | stage.calculateFps();
31 | setTimeout(runLoop, 16.666666666666668);
32 |
33 | if (!isIdle) {
34 | stage.shManager.cleanup();
35 | stage.eventBus.emit('idle');
36 | isIdle = true;
37 | }
38 |
39 | if (stage.txMemManager.checkCleanup() === true) {
40 | stage.txMemManager.cleanup(false);
41 | }
42 |
43 | stage.flushFrameEvents();
44 | return;
45 | }
46 |
47 | isIdle = false;
48 | stage.drawFrame();
49 | stage.flushFrameEvents();
50 | requestAnimationFrame(runLoop);
51 | };
52 | requestAnimationFrame(runLoop);
53 | }
54 |
55 | ////////////////////////
56 | // ImageBitmap
57 | ////////////////////////
58 |
59 | override createImageBitmap(
60 | blob: ImageBitmapSource,
61 | sxOrOptions?: number | ImageBitmapOptions,
62 | sy?: number,
63 | sw?: number,
64 | sh?: number,
65 | options?: ImageBitmapOptions,
66 | ): Promise {
67 | if (typeof sxOrOptions === 'number') {
68 | return createImageBitmap(
69 | blob,
70 | sxOrOptions,
71 | sy ?? 0,
72 | sw ?? 0,
73 | sh ?? 0,
74 | options,
75 | );
76 | } else {
77 | return createImageBitmap(blob, sxOrOptions);
78 | }
79 | }
80 |
81 | getTimeStamp(): number {
82 | return performance ? performance.now() : Date.now();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/core/renderers/CoreContextTexture.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { TextureMemoryManager } from '../TextureMemoryManager.js';
21 | import type { Texture } from '../textures/Texture.js';
22 |
23 | export abstract class CoreContextTexture {
24 | readonly textureSource: Texture;
25 | private memManager: TextureMemoryManager;
26 | public state: 'freed' | 'loading' | 'loaded' | 'failed' = 'freed';
27 |
28 | constructor(memManager: TextureMemoryManager, textureSource: Texture) {
29 | this.memManager = memManager;
30 | this.textureSource = textureSource;
31 | }
32 |
33 | protected setTextureMemUse(byteSize: number): void {
34 | this.memManager.setTextureMemUse(this.textureSource, byteSize);
35 | }
36 |
37 | abstract load(): void;
38 | abstract free(): void;
39 |
40 | get renderable(): boolean {
41 | return this.textureSource.renderable;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/core/renderers/CoreRenderOp.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | export abstract class CoreRenderOp {
21 | abstract draw(): void;
22 | }
23 |
--------------------------------------------------------------------------------
/src/core/renderers/CoreShaderProgram.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | export interface CoreShaderProgram {
21 | attach?: () => void;
22 | detach?: () => void;
23 | }
24 |
--------------------------------------------------------------------------------
/src/core/renderers/webgl/WebGlCtxSubTexture.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { Dimensions } from '../../../common/CommonTypes.js';
21 | import { assertTruthy } from '../../../utils.js';
22 | import type { TextureMemoryManager } from '../../TextureMemoryManager.js';
23 | import type { WebGlContextWrapper } from '../../lib/WebGlContextWrapper.js';
24 | import type { SubTexture } from '../../textures/SubTexture.js';
25 | import { WebGlCtxTexture } from './WebGlCtxTexture.js';
26 |
27 | export class WebGlCtxSubTexture extends WebGlCtxTexture {
28 | constructor(
29 | glw: WebGlContextWrapper,
30 | memManager: TextureMemoryManager,
31 | textureSource: SubTexture,
32 | ) {
33 | super(glw, memManager, textureSource);
34 | }
35 |
36 | override async onLoadRequest(): Promise {
37 | const props = (this.textureSource as SubTexture).textureData;
38 | assertTruthy(props, 'SubTexture must have texture data');
39 |
40 | if (props.data instanceof Uint8Array) {
41 | // its a 1x1 Color Texture
42 | return { width: 1, height: 1 };
43 | }
44 |
45 | return {
46 | width: props.data?.width || 0,
47 | height: props.data?.height || 0,
48 | };
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/core/renderers/webgl/internal/BufferCollection.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { AttributeInfo } from './ShaderUtils.js';
21 |
22 | export interface BufferItem {
23 | buffer: WebGLBuffer;
24 | attributes: Record;
25 | }
26 |
27 | /**
28 | * Represents a collection of WebGL Buffers along with their associated
29 | * vertex attribute formats.
30 | */
31 | export class BufferCollection {
32 | constructor(readonly config: BufferItem[]) {}
33 |
34 | /**
35 | * Get the WebGLBuffer associated with the given attribute name if it exists.
36 | *
37 | * @param attributeName
38 | * @returns
39 | */
40 | getBuffer(attributeName: string): WebGLBuffer | undefined {
41 | return this.config.find((item) => item.attributes[attributeName])?.buffer;
42 | }
43 |
44 | /**
45 | * Get the AttributeInfo associated with the given attribute name if it exists.
46 | *
47 | * @param attributeName
48 | * @returns
49 | */
50 | getAttributeInfo(attributeName: string): AttributeInfo | undefined {
51 | return this.config.find((item) => item.attributes[attributeName])
52 | ?.attributes[attributeName];
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/core/renderers/webgl/internal/WebGlUtils.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | /**
21 | * Generic WebGL Utility Functions
22 | *
23 | * @remarks
24 | * Nothing here should be coupled to Renderer logic / types.
25 | *
26 | * @param gl
27 | * @returns
28 | */
29 | export function isWebGl2(
30 | gl: WebGLRenderingContext,
31 | ): gl is WebGL2RenderingContext {
32 | return (
33 | self.WebGL2RenderingContext && gl instanceof self.WebGL2RenderingContext
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/src/core/shaders/canvas/HolePunch.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import { calcFactoredRadiusArray } from '../../lib/utils.js';
19 | import type { CanvasShaderType } from '../../renderers/canvas/CanvasShaderNode.js';
20 | import type { Vec4 } from '../../renderers/webgl/internal/ShaderUtils.js';
21 | import {
22 | HolePunchTemplate,
23 | type HolePunchProps,
24 | } from '../templates/HolePunchTemplate.js';
25 | import { roundRect } from './utils/render.js';
26 |
27 | export interface ComputedHolePunchValues {
28 | radius: Vec4;
29 | }
30 |
31 | export const HolePunch: CanvasShaderType<
32 | HolePunchProps,
33 | ComputedHolePunchValues
34 | > = {
35 | props: HolePunchTemplate.props,
36 | update() {
37 | this.computed.radius = calcFactoredRadiusArray(
38 | this.props!.radius as Vec4,
39 | this.props!.width,
40 | this.props!.height,
41 | );
42 | },
43 | render(ctx, quad, renderContext) {
44 | ctx.save();
45 | renderContext();
46 | const { x, y, width, height } = this.props!;
47 | ctx.beginPath();
48 | roundRect(
49 | ctx,
50 | quad.tx + x,
51 | quad.ty + y,
52 | width,
53 | height,
54 | this.computed.radius!,
55 | );
56 | ctx.closePath();
57 | ctx.fillStyle = 'black';
58 | ctx.globalCompositeOperation = 'destination-out';
59 | ctx.fill();
60 | ctx.restore();
61 | },
62 | };
63 |
--------------------------------------------------------------------------------
/src/core/shaders/canvas/Rounded.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import { calcFactoredRadiusArray } from '../../lib/utils.js';
19 | import type { CanvasShaderType } from '../../renderers/canvas/CanvasShaderNode.js';
20 | import type { Vec4 } from '../../renderers/webgl/internal/ShaderUtils.js';
21 | import {
22 | RoundedTemplate,
23 | type RoundedProps,
24 | } from '../templates/RoundedTemplate.js';
25 | import { roundRect } from './utils/render.js';
26 |
27 | export interface ComputedRoundedValues {
28 | radius: Vec4;
29 | }
30 |
31 | export const Rounded: CanvasShaderType = {
32 | props: RoundedTemplate.props,
33 | saveAndRestore: true,
34 | update(node) {
35 | this.computed.radius = calcFactoredRadiusArray(
36 | this.props!.radius as Vec4,
37 | node.width,
38 | node.height,
39 | );
40 | },
41 | render(ctx, quad, renderContext) {
42 | const path = new Path2D();
43 | roundRect(
44 | path,
45 | quad.tx,
46 | quad.ty,
47 | quad.width,
48 | quad.height,
49 | this.computed.radius!,
50 | );
51 | ctx.clip(path);
52 |
53 | renderContext();
54 | },
55 | };
56 |
--------------------------------------------------------------------------------
/src/core/shaders/canvas/Shadow.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { CanvasShaderType } from '../../renderers/canvas/CanvasShaderNode.js';
19 | import type { Vec4 } from '../../renderers/webgl/internal/ShaderUtils.js';
20 | import {
21 | ShadowTemplate,
22 | type ShadowProps,
23 | } from '../templates/ShadowTemplate.js';
24 | import { shadow } from './utils/render.js';
25 |
26 | export interface ComputedShadowValues {
27 | shadowColor: string;
28 | shadowRadius: Vec4;
29 | }
30 |
31 | export const Shadow: CanvasShaderType = {
32 | props: ShadowTemplate.props,
33 | update() {
34 | this.computed.shadowColor = this.toColorString(this.props!['color']);
35 | const blur = this.props!['blur'];
36 | this.computed.shadowRadius = [blur, blur, blur, blur];
37 | },
38 | render(ctx, quad, renderContext) {
39 | shadow(
40 | ctx,
41 | quad.tx,
42 | quad.ty,
43 | quad.width,
44 | quad.height,
45 | this.computed.shadowColor!,
46 | this.props!['projection'],
47 | this.computed.shadowRadius!,
48 | this.stage.pixelRatio,
49 | );
50 | renderContext();
51 | },
52 | };
53 |
--------------------------------------------------------------------------------
/src/core/shaders/templates/LinearGradientTemplate.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { CoreShaderType } from '../../renderers/CoreShaderNode.js';
19 |
20 | /**
21 | * Properties of the {@link LinearGradient} shader
22 | */
23 | export interface LinearGradientProps {
24 | /**
25 | * Array of colors to be used in the LinearGradient shader
26 | *
27 | * @default [0xff000000, 0xffffffff]
28 | */
29 | colors: number[];
30 | /**
31 | * Angle of the LinearGradient shader, Angle in Radians
32 | *
33 | * @default 0
34 | */
35 | angle: number;
36 | /**
37 | * Array of color stops
38 | */
39 | stops: number[];
40 | }
41 |
42 | export const LinearGradientTemplate: CoreShaderType = {
43 | props: {
44 | colors: {
45 | default: [0x000000ff, 0xffffffff],
46 | resolve(value) {
47 | if (value !== undefined && value.length > 0) {
48 | return value;
49 | }
50 | return ([] as number[]).concat(this.default);
51 | },
52 | },
53 | stops: {
54 | default: [0, 1],
55 | resolve(value, props) {
56 | if (value !== undefined && value.length === props.colors.length) {
57 | return value;
58 | }
59 | if (value === undefined) {
60 | value = [];
61 | }
62 | const len = props.colors.length;
63 | for (let i = 0; i < len; i++) {
64 | value[i] = i * (1 / (len - 1));
65 | }
66 | return value;
67 | },
68 | },
69 | angle: 0,
70 | },
71 | };
72 |
--------------------------------------------------------------------------------
/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { CoreShaderType } from '../../renderers/CoreShaderNode.js';
19 | import { getBorderProps, type BorderProps } from './BorderTemplate.js';
20 | import { RoundedTemplate, type RoundedProps } from './RoundedTemplate.js';
21 | import type { PrefixedType } from '../utils.js';
22 | import { getShadowProps, type ShadowProps } from './ShadowTemplate.js';
23 |
24 | export type RoundedWithBorderAndShadowProps = RoundedProps &
25 | PrefixedType &
26 | PrefixedType;
27 |
28 | const props = Object.assign(
29 | {},
30 | RoundedTemplate.props,
31 | getBorderProps('border'),
32 | getShadowProps('shadow'),
33 | ) as RoundedWithBorderAndShadowProps;
34 |
35 | export const RoundedWithBorderAndShadowTemplate: CoreShaderType =
36 | {
37 | props,
38 | };
39 |
--------------------------------------------------------------------------------
/src/core/shaders/templates/RoundedWithBorderTemplate.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { CoreShaderType } from '../../renderers/CoreShaderNode.js';
19 | import { getBorderProps, type BorderProps } from './BorderTemplate.js';
20 | import { RoundedTemplate, type RoundedProps } from './RoundedTemplate.js';
21 | import type { PrefixedType } from '../utils.js';
22 |
23 | export type RoundedWithBorderProps = RoundedProps &
24 | PrefixedType;
25 |
26 | const props = Object.assign(
27 | {},
28 | RoundedTemplate.props,
29 | getBorderProps('border'),
30 | ) as RoundedWithBorderProps;
31 |
32 | export const RoundedWithBorderTemplate: CoreShaderType =
33 | {
34 | props,
35 | };
36 |
--------------------------------------------------------------------------------
/src/core/shaders/templates/RoundedWithShadowTemplate.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 |
18 | import type { CoreShaderType } from '../../renderers/CoreShaderNode.js';
19 | import { RoundedTemplate, type RoundedProps } from './RoundedTemplate.js';
20 | import type { PrefixedType } from '../utils.js';
21 | import { getShadowProps, type ShadowProps } from './ShadowTemplate.js';
22 |
23 | export type RoundedWithShadowProps = RoundedProps &
24 | PrefixedType;
25 |
26 | const props = Object.assign(
27 | {},
28 | RoundedTemplate.props,
29 | getShadowProps('shadow'),
30 | ) as RoundedWithShadowProps;
31 |
32 | export const RoundedWithShadowTemplate: CoreShaderType =
33 | {
34 | props,
35 | };
36 |
--------------------------------------------------------------------------------
/src/core/shaders/utils.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Comcast Cable Communications Management, LLC
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | *
15 | * SPDX-License-Identifier: Apache-2.0
16 | */
17 | import { assertTruthy } from '../../utils.js';
18 | import type { Vec4 } from '../renderers/webgl/internal/ShaderUtils.js';
19 |
20 | export const validateArrayLength4 = (value: number | number[]): Vec4 => {
21 | if (!Array.isArray(value)) {
22 | return [value, value, value, value];
23 | }
24 | assertTruthy(value);
25 | if (value.length === 4) {
26 | return value as Vec4;
27 | }
28 | if (value.length === 3) {
29 | value[3] = value[0]!;
30 | return value as Vec4;
31 | }
32 | if (value.length === 2) {
33 | value[2] = value[0]!;
34 | value[3] = value[1]!;
35 | return value as Vec4;
36 | }
37 | value[0] = value[0] || 0;
38 | value[1] = value[0];
39 | value[2] = value[0];
40 | value[3] = value[0];
41 | return value as Vec4;
42 | };
43 |
44 | export type PrefixedType = {
45 | [Key in keyof T as P extends string ? `${P}-${string & Key}` : Key]: T[Key];
46 | };
47 |
--------------------------------------------------------------------------------
/src/core/text-rendering/TextRenderingUtils.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2024 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | import type { NormalizedFontMetrics } from './font-face-types/TrFontFace.js';
20 |
21 | /**
22 | * Calculate the default line height given normalized font metrics
23 | *
24 | * @remarks
25 | * This method may be used for both the WebTrFontFace and SdfTrFontFace font types.
26 | *
27 | * @param metrics
28 | * @param fontSize
29 | * @returns
30 | */
31 | export function calcDefaultLineHeight(
32 | metrics: NormalizedFontMetrics,
33 | fontSize: number,
34 | ): number {
35 | return fontSize * (metrics.ascender - metrics.descender + metrics.lineGap);
36 | }
37 |
--------------------------------------------------------------------------------
/src/core/text-rendering/font-face-types/utils.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2020 Metrological
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | export function fetchJson(
20 | url: string,
21 | responseType: XMLHttpRequestResponseType = '',
22 | ): Promise {
23 | return new Promise((resolve, reject) => {
24 | const xhr = new XMLHttpRequest();
25 | xhr.responseType = responseType;
26 | xhr.onreadystatechange = function () {
27 | if (xhr.readyState == XMLHttpRequest.DONE) {
28 | // On most devices like WebOS and Tizen, the file protocol returns 0 while http(s) protocol returns 200
29 | if (xhr.status === 0 || xhr.status === 200) {
30 | resolve(xhr.response);
31 | } else {
32 | reject(xhr.statusText);
33 | }
34 | }
35 | };
36 | xhr.open('GET', url, true);
37 | xhr.send(null);
38 | });
39 | }
40 |
--------------------------------------------------------------------------------
/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.test.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import { describe, expect, it } from 'vitest';
21 | import { PeekableIterator } from './PeekableGenerator.js';
22 |
23 | describe('PeekableIterator', () => {
24 | it('should be able to peek at the next value.', () => {
25 | const iterator = new PeekableIterator([1, 2, 3].values());
26 | expect(iterator.peek()).toEqual({ done: false, value: 1 });
27 | expect(iterator.next()).toEqual({ done: false, value: 1 });
28 | expect(iterator.peek()).toEqual({ done: false, value: 2 });
29 | expect(iterator.next()).toEqual({ done: false, value: 2 });
30 | expect(iterator.peek()).toEqual({ done: false, value: 3 });
31 | expect(iterator.next()).toEqual({ done: false, value: 3 });
32 | expect(iterator.peek()).toEqual({ done: true, value: undefined });
33 | expect(iterator.next()).toEqual({ done: true, value: undefined });
34 | });
35 |
36 | it('should be able to return the last index of the iterator.', () => {
37 | const iterator = new PeekableIterator([1, 2, 3].values());
38 | expect(iterator.lastIndex).toBe(-1);
39 | iterator.next();
40 | expect(iterator.lastIndex).toBe(0);
41 | iterator.next();
42 | expect(iterator.lastIndex).toBe(1);
43 | iterator.next();
44 | expect(iterator.lastIndex).toBe(2);
45 | iterator.next();
46 | expect(iterator.lastIndex).toBe(-1);
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/src/core/text-rendering/renderers/SdfTextRenderer/internal/PeekableGenerator.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | /**
21 | * A wrapper Generator class that makes a generator peekable.
22 | */
23 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
24 | export class PeekableIterator
25 | implements Iterator
26 | {
27 | private peekBuffer: IteratorResult[] = [];
28 | private _lastIndex;
29 |
30 | constructor(private iterator: Iterator, indexBase = 0) {
31 | this.iterator = iterator;
32 | this._lastIndex = indexBase - 1;
33 | this.peekBuffer = [];
34 | }
35 |
36 | next(): IteratorResult {
37 | const nextResult =
38 | this.peekBuffer.length > 0
39 | ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
40 | this.peekBuffer.pop()!
41 | : this.iterator.next();
42 |
43 | if (nextResult.done) {
44 | this._lastIndex = -1;
45 | } else {
46 | this._lastIndex++;
47 | }
48 | return nextResult;
49 | }
50 |
51 | peek(): IteratorResult {
52 | if (this.peekBuffer.length > 0) {
53 | // We know that the buffer is not empty, so we can safely use the
54 | // non-null assertion operator
55 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
56 | return this.peekBuffer[0]!;
57 | }
58 | const result = this.iterator.next();
59 | this.peekBuffer.push(result);
60 | return result;
61 | }
62 |
63 | get lastIndex(): number {
64 | return this._lastIndex;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/core/text-rendering/renderers/SdfTextRenderer/internal/SpecialCodepoints.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | export const SpecialCodepoints = {
21 | LINE_FEED: 0x0a,
22 | CARRIAGE_RETURN: 0x0d,
23 | SPACE: 0x20,
24 | TAB: 0x09,
25 | ZERO_WIDTH_SPACE: 0x200b,
26 | ZERO_WIDTH_NON_JOINER: 0x200c,
27 | ZERO_WIDTH_JOINER: 0x200d,
28 | LEFT_TO_RIGHT_MARK: 0x200e,
29 | RIGHT_TO_LEFT_MARK: 0x200f,
30 | LEFT_TO_RIGHT_EMBEDDING: 0x202a,
31 | RIGHT_TO_LEFT_EMBEDDING: 0x202b,
32 | POP_DIRECTIONAL_FORMATTING: 0x202c,
33 | LEFT_TO_RIGHT_OVERRIDE: 0x202d,
34 | RIGHT_TO_LEFT_OVERRIDE: 0x202e,
35 | LINE_SEPARATOR: 0x2028,
36 | PARAGRAPH_SEPARATOR: 0x2029,
37 | OBJECT_REPLACEMENT_CHARACTER: 0xfffc,
38 | REPLACEMENT_CHARACTER: 0xfffd,
39 | ZERO_WIDTH_NO_BREAK_SPACE: 0xfeff,
40 | LEFT_TO_RIGHT_ISOLATE: 0x2066,
41 | RIGHT_TO_LEFT_ISOLATE: 0x2067,
42 | FIRST_STRONG_ISOLATE: 0x2068,
43 | POP_DIRECTIONAL_ISOLATE: 0x2069,
44 | INHIBIT_SYMMETRIC_SWAPPING: 0x206a,
45 | ACTIVATE_SYMMETRIC_SWAPPING: 0x206b,
46 | INHIBIT_ARABIC_FORM_SHAPING: 0x206c,
47 | ACTIVATE_ARABIC_FORM_SHAPING: 0x206d,
48 | NATIONAL_DIGIT_SHAPES: 0x206e,
49 | NOMINAL_DIGIT_SHAPES: 0x206f,
50 | LEFT_TO_RIGHT_BOUNDARY: 0x200e,
51 | RIGHT_TO_LEFT_BOUNDARY: 0x200f,
52 | };
53 |
--------------------------------------------------------------------------------
/src/core/text-rendering/renderers/SdfTextRenderer/internal/constants.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | /**
21 | * Number of floating point numbers that represent a single glyph in the SDF vertex buffer.
22 | *
23 | * @remarks
24 | * The vertex buffer contains:
25 | * - 6 vertex positions
26 | * - 6 texture coordinates
27 | * - = 12 positions/coordinates per glyph
28 | *
29 | * Each vertex position and texture coordinate consist of 2 floating point numbers (x/y).
30 | * So there are 12 * 2 = 24 floating point numbers that make up a single glyph.
31 | */
32 | export const FLOATS_PER_GLYPH = 24;
33 |
--------------------------------------------------------------------------------
/src/core/text-rendering/renderers/SdfTextRenderer/internal/getUnicodeCodepoints.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | // Reversible Generator Wrapper Class
21 |
22 | /**
23 | * Generator function that yields each Unicode code point in the given string.
24 | */
25 | export function* getUnicodeCodepoints(
26 | text: string,
27 | start = 0,
28 | ): Generator {
29 | let i = start;
30 | while (i < text.length) {
31 | const codePoint = text.codePointAt(i);
32 | if (codePoint === undefined) {
33 | throw new Error('Invalid Unicode code point');
34 | }
35 | yield codePoint;
36 | i += codePoint <= 0xffff ? 1 : 2;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.test.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import { expect, describe, it } from 'vitest';
21 | import { measureText } from './measureText.js';
22 | import sdfData from 'test/mockdata/Ubuntu-Bold.msdf.json';
23 | import {
24 | SdfFontShaper,
25 | type SdfFontData,
26 | } from '../../../font-face-types/SdfTrFontFace/internal/SdfFontShaper.js';
27 |
28 | const glyphMap = new Map();
29 | sdfData.chars.forEach((glyph) => {
30 | glyphMap.set(glyph.id, glyph);
31 | });
32 |
33 | describe('measureText', () => {
34 | it('should measure text width', () => {
35 | const PERIOD_WIDTH = 10.332;
36 | const shaper = new SdfFontShaper(
37 | sdfData as unknown as SdfFontData,
38 | glyphMap,
39 | );
40 | expect(measureText('', { letterSpacing: 0 }, shaper)).toBe(0);
41 | expect(measureText('.', { letterSpacing: 0 }, shaper)).toBe(PERIOD_WIDTH);
42 | expect(measureText('..', { letterSpacing: 0 }, shaper)).toBeCloseTo(
43 | PERIOD_WIDTH * 2,
44 | );
45 | expect(measureText('..', { letterSpacing: 5 }, shaper)).toBeCloseTo(
46 | PERIOD_WIDTH * 2 + 5,
47 | );
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/src/core/text-rendering/renderers/SdfTextRenderer/internal/measureText.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type {
21 | FontShaper,
22 | FontShaperProps,
23 | } from '../../../font-face-types/SdfTrFontFace/internal/FontShaper.js';
24 | import { PeekableIterator } from './PeekableGenerator.js';
25 | import { getUnicodeCodepoints } from './getUnicodeCodepoints.js';
26 |
27 | /**
28 | * Measures a single-line of text width ignoring any unmapped glyphs including line breaks
29 | *
30 | * @param text
31 | * @param shaperProps
32 | * @param shaper
33 | * @returns
34 | */
35 | export function measureText(
36 | text: string,
37 | shaperProps: FontShaperProps,
38 | shaper: FontShaper,
39 | ): number {
40 | const glyphs = shaper.shapeText(
41 | shaperProps,
42 | new PeekableIterator(getUnicodeCodepoints(text, 0), 0),
43 | );
44 | let width = 0;
45 | for (const glyph of glyphs) {
46 | if (glyph.mapped && glyph.codepoint !== 8203) {
47 | // Skip ZWSP (\u200B)
48 | width += glyph.xAdvance;
49 | }
50 | }
51 | return width;
52 | }
53 |
--------------------------------------------------------------------------------
/src/core/text-rendering/renderers/SdfTextRenderer/internal/util.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | /**
21 | * Round up to the nearest multiple of the given number.
22 | *
23 | * @param value
24 | * @param multiple
25 | * @returns
26 | */
27 | export function roundUpToMultiple(value: number, multiple: number) {
28 | return Math.ceil(value / multiple) * multiple;
29 | }
30 |
31 | /**
32 | * Round down to the nearest multiple of the given number.
33 | *
34 | * @param value
35 | * @param multiple
36 | * @returns
37 | */
38 | export function roundDownToMultiple(value: number, multiple: number) {
39 | return Math.floor(value / multiple) * multiple;
40 | }
41 |
--------------------------------------------------------------------------------
/src/core/textures/RenderTexture.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * If not stated otherwise in this file or this component's LICENSE file the
3 | * following copyright and licenses apply:
4 | *
5 | * Copyright 2023 Comcast Cable Communications Management, LLC.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the License);
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import type { CoreTextureManager } from '../CoreTextureManager.js';
21 | import { Texture, TextureType, type TextureData } from './Texture.js';
22 |
23 | /**
24 | * Properties of the {@link RenderTexture}
25 | */
26 | export interface RenderTextureProps {
27 | /**
28 | * WebGL Texture width
29 | * @default 256
30 | */
31 | width?: number;
32 |
33 | /**
34 | * WebGL Texture height
35 | * @default 256
36 | */
37 | height?: number;
38 | }
39 |
40 | export class RenderTexture extends Texture {
41 | props: Required;
42 |
43 | public override type: TextureType = TextureType.renderToTexture;
44 |
45 | constructor(txManager: CoreTextureManager, props?: RenderTextureProps) {
46 | super(txManager);
47 | this.props = RenderTexture.resolveDefaults(props || {});
48 | }
49 |
50 | get width() {
51 | return this.props.width;
52 | }
53 |
54 | set width(value: number) {
55 | this.props.width = value;
56 | }
57 |
58 | get height() {
59 | return this.props.height;
60 | }
61 |
62 | set height(value: number) {
63 | this.props.height = value;
64 | }
65 |
66 | override async getTextureSource(): Promise {
67 | this.setState('fetched');
68 |
69 | return {
70 | data: null,
71 | premultiplyAlpha: null,
72 | };
73 | }
74 |
75 | static override resolveDefaults(
76 | props: RenderTextureProps,
77 | ): Required {
78 | return {
79 | width: props.width || 256,
80 | height: props.height || 256,
81 | };
82 | }
83 |
84 | static z$__type__Props: RenderTextureProps;
85 | }
86 |
--------------------------------------------------------------------------------
/src/env.d.ts:
--------------------------------------------------------------------------------
1 | interface ImportMetaEnv {
2 | readonly PROD: boolean;
3 | }
4 |
5 | interface ImportMeta {
6 | readonly env: ImportMetaEnv;
7 | }
8 |
--------------------------------------------------------------------------------
/src/main-api/utils.ts:
--------------------------------------------------------------------------------
1 | import type { CustomDataMap } from '../core/CoreNode.js';
2 |
3 | export function santizeCustomDataMap(d: CustomDataMap): CustomDataMap {
4 | const validTypes = {
5 | boolean: true,
6 | string: true,
7 | number: true,
8 | undefined: true,
9 | };
10 |
11 | const keys = Object.keys(d);
12 | for (let i = 0; i < keys.length; i++) {
13 | const key = keys[i];
14 | if (!key) {
15 | continue;
16 | }
17 |
18 | const value = d[key];
19 | const valueType = typeof value;
20 |
21 | // Typescript doesn't understand the above const valueType ¯\_(ツ)_/¯
22 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
23 | // @ts-ignore-next-line
24 | if (valueType === 'string' && value.length > 2048) {
25 | console.warn(
26 | `Custom Data value for ${key} is too long, it will be truncated to 2048 characters`,
27 | );
28 |
29 | // same here, see above comment, this can only be a string at this point
30 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
31 | // @ts-ignore-next-line
32 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
33 | d[key] = value.substring(0, 2048);
34 | }
35 |
36 | if (!validTypes[valueType as keyof typeof validTypes]) {
37 | console.warn(
38 | `Custom Data value for ${key} is not a boolean, string, or number, it will be ignored`,
39 | );
40 | delete d[key];
41 | }
42 | }
43 |
44 | return d;
45 | }
46 |
--------------------------------------------------------------------------------
/tsconfig.cfg.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "dist-cfg",
4 | "types": ["@types/node"],
5 | "target": "ESNext",
6 | "module": "Node16",
7 | "moduleResolution": "Node16",
8 | "composite": true,
9 | "resolveJsonModule": true,
10 | "allowJs": true,
11 | "esModuleInterop": true,
12 | },
13 | "files": [
14 | "./examples/vite.config.ts",
15 | "./typedoc.config.cjs"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/tsconfig.dist.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "composite": true,
5 | },
6 | "include": ["./src/**/*.ts", "./exports/**/*.ts"],
7 | "exclude": ["node_modules", "./**/*.test.ts"],
8 | }
9 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "rootDir": ".",
4 | "types": [],
5 | "lib": ["ES2022", "DOM"],
6 | "outDir": "dist",
7 | "allowJs": true,
8 | "target": "ES2022",
9 | "module": "Node16",
10 | "moduleResolution": "Node16",
11 | "sourceMap": true,
12 | "declaration": true,
13 | "experimentalDecorators": true,
14 |
15 | // Type Checking / Syntax Rules
16 | "strict": true,
17 | "noUncheckedIndexedAccess": true,
18 | "noImplicitOverride": true,
19 | "noImplicitAny": false,
20 | "allowSyntheticDefaultImports": true,
21 | "resolveJsonModule": true,
22 | "verbatimModuleSyntax": true,
23 | "composite": true,
24 | },
25 | "files": [],
26 | "references": [
27 | {
28 | "path": "./tsconfig.cfg.json"
29 | },
30 | {
31 | "path": "./tsconfig.vitest.json"
32 | },
33 | {
34 | "path": "./tsconfig.dist.json"
35 | }
36 | ],
37 | }
38 |
--------------------------------------------------------------------------------
/tsconfig.vitest.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "dist-vitest",
5 | "types": [],
6 | "composite": true,
7 | "module": "esnext",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "paths": {
11 | "test/*": ["./test/*"]
12 | },
13 | },
14 | "include": [
15 | "./src/**/*.ts",
16 | "./exports/**/*.ts",
17 | "./test/mockdata/**/*.json"
18 | ],
19 | "exclude": [
20 | "./src/core/renderers/webgl/effect/*.ts"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/typedoc.config.cjs:
--------------------------------------------------------------------------------
1 | /* global module */
2 | /** @type {import('typedoc').TypeDocOptions} */
3 | module.exports = {
4 | entryPoints: [
5 | './exports/index.ts',
6 | './exports/webgl.ts',
7 | './exports/webgl-shaders.ts',
8 | './exports/canvas.ts',
9 | './exports/canvas-shaders.ts',
10 | './exports/utils.ts',
11 | ],
12 | out: 'typedocs',
13 | };
14 |
--------------------------------------------------------------------------------
/visual-regression/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict = true
2 |
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/alignment-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/alignment-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/alpha-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/alpha-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/alpha-blending-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/alpha-blending-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/alpha-blending-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/alpha-blending-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/animation-events_a1-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/animation-events_a1-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/animation-events_a1-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/animation-events_a1-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/animation-events_a1-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/animation-events_a1-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/animation-events_a2-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/animation-events_a2-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/animation-events_a2-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/animation-events_a2-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/animation-events_a2-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/animation-events_a2-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/animation-events_a3-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/animation-events_a3-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/animation-events_a3-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/animation-events_a3-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/clear-color-setting-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/clipping-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/clipping-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/clipping-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/clipping-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/clipping-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/clipping-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/clipping-mutations-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/clipping-mutations-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/clipping-mutations-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/clipping-mutations-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/clipping-mutations-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/clipping-mutations-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/destroy-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/destroy-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/destroy-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/destroy-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/ds-effect-radial-progress-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/ds-effect-radial-progress-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/dynamic-shader-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/dynamic-shader-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/dynamic-shader-circle-border-radius-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/dynamic-shader-circle-border-radius-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/hole-punch-effect-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/hole-punch-effect-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/quads-rendered-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/quads-rendered-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/quads-rendered-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/quads-rendered-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/render-settings-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/render-settings-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/render-settings-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/render-settings-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/render-settings-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/render-settings-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/render-settings-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/render-settings-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/render-settings-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/render-settings-5.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/render-settings-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/render-settings-6.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/resize-mode-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/resize-mode-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/resize-mode-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/resize-mode-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/resize-mode-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/resize-mode-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/resize-mode-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/resize-mode-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-5.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/rtt-dimension-6.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/rtt-spritemap-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/rtt-spritemap-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/scaling-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/scaling-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/scaling-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/scaling-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/scaling-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/scaling-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/shader-animation_animation1-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/shader-animation_animation1-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/shader-animation_animation2-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/shader-animation_animation2-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/shader-animation_startup-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/shader-animation_startup-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/shader-border-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/shader-border-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/shader-hole-punch-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/shader-hole-punch-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/shader-linear-gradient-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/shader-linear-gradient-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/shader-radial-gradient-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/shader-radial-gradient-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/shader-rounded-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/shader-rounded-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/shader-shadow-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/shader-shadow-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-align-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-align-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-align-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-align-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-align-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-align-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-align-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-align-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-align-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-align-5.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-align-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-align-6.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-alpha-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-alpha-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-alpha-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-alpha-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-baseline-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-baseline-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-canvas-font-no-metrics-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-canvas-font-no-metrics-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-canvas-font-no-metrics-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-canvas-font-no-metrics-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-10.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-5.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-6.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-7.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-8.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-contain-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-contain-9.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-dimensions-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-dimensions-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-dimensions-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-dimensions-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-dimensions-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-dimensions-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-dimensions-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-dimensions-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-dimensions-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-dimensions-5.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-dimensions-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-dimensions-6.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-dimensions-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-dimensions-7.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-modified-metrics-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-modified-metrics-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-modified-metrics-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-modified-metrics-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-modified-metrics-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-layout-consistency-modified-metrics-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-line-height-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-line-height-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-max-lines-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-max-lines-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-max-lines-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-max-lines-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-mixed-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-mixed-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-5.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-offscreen-move-6.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-overflow-suffix-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-overflow-suffix-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-rotation-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-rotation-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-rotation-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-rotation-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-scaling-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-scaling-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-scaling-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-scaling-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-scaling-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-scaling-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-scaling-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-scaling-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-scaling-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-scaling-5.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-scaling-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-scaling-6.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-ssdf-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-ssdf-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-vertical-align-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-vertical-align-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-vertical-align-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-vertical-align-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-wordbreak-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-wordbreak-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-wordbreak-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-wordbreak-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-wordbreak-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-wordbreak-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-wordbreak-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-wordbreak-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-zwsp-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-zwsp-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-zwsp-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-zwsp-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/text-zwsp-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/text-zwsp-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/texture-autosize-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/texture-autosize-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/texture-base64-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/texture-base64-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/texture-factory-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/texture-factory-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/texture-source-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/texture-source-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/texture-spritemap-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/texture-spritemap-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/texture-svg-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/texture-svg-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/textures-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/textures-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-10.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-11.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-12.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-5.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-6.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-7.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-8.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-boundsmargin-9.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-10.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-11.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-12.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-13.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-14.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-15.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-16.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-17.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-18.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-4.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-5.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-6.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-7.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-8.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-events-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-events-9.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-largebound-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-largebound-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-largebound-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-largebound-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-largebound-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-largebound-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-strictbounds-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-strictbounds-1.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-strictbounds-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-strictbounds-2.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/viewport-strictbounds-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/viewport-strictbounds-3.png
--------------------------------------------------------------------------------
/visual-regression/certified-snapshots/chromium-ci/zIndex-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightning-js/renderer/d4867e5855e38a75f4875c8172fba883afa0a761/visual-regression/certified-snapshots/chromium-ci/zIndex-1.png
--------------------------------------------------------------------------------
/visual-regression/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "visual-regression",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "private": true,
8 | "scripts": {
9 | "start": "pnpm test:visual",
10 | "test:visual": "tsc && node dist/src/index.js",
11 | "build": "tsc",
12 | "build:renderer": "cd .. && pnpm build",
13 | "build:examples": "cd ../examples && pnpm build",
14 | "build:docker": "tsc && node dist/src/build-docker.js",
15 | "serve-examples": "cd ../examples && pnpm preview:automation",
16 | "node-version": "node --version"
17 | },
18 | "keywords": [],
19 | "author": "",
20 | "license": "Apache-2.0",
21 | "devDependencies": {
22 | "@types/fs-extra": "^11.0.4",
23 | "@types/node": "^18.18.6",
24 | "@types/pixelmatch": "^5.2.6",
25 | "@types/pngjs": "^6.0.5",
26 | "@types/yargs": "^17.0.31",
27 | "playwright": "^1.39.0",
28 | "wait-port": "^1.1.0"
29 | },
30 | "dependencies": {
31 | "chalk": "^5.3.0",
32 | "execa": "^8.0.1",
33 | "fs-extra": "^11.1.1",
34 | "yargs": "^17.7.2",
35 | "pngjs": "^7.0.0",
36 | "pixelmatch": "^6.0.0"
37 | },
38 | "engines": {
39 | "npm": "please-use-pnpm"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/visual-regression/src/build-docker.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ts-node
2 |
3 | import { $ } from 'execa';
4 | import { argv } from 'process';
5 | import path from 'path';
6 | import { fileURLToPath } from 'url';
7 |
8 | import { detectContainerRuntime } from './detectDockerRuntime.js';
9 |
10 | /**
11 | * Builds a container image using the detected container runtime.
12 | * Changes the working directory to one level higher than the script's location.
13 | * @param runtime - The container runtime (`podman` or `docker`).
14 | * @param imageName - The name of the container image to build.
15 | */
16 | async function buildContainer(
17 | runtime: string,
18 | imageName: string,
19 | ): Promise {
20 | // Change working directory to one level higher than the script's location
21 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
22 | const scriptDir = path.resolve(__dirname, '../../../');
23 | process.chdir(scriptDir);
24 |
25 | console.log(`Working directory changed to: ${scriptDir}`);
26 | console.log(`Using ${runtime} to build the container image: ${imageName}`);
27 | try {
28 | await $({ stdio: 'inherit' })`${runtime} build -t ${imageName} .`;
29 | } catch (error) {
30 | console.error(`Failed to build the image with ${runtime}.`, error);
31 | process.exit(1);
32 | }
33 | }
34 |
35 | (async () => {
36 | const imageName = argv[2] || 'visual-regression'; // Default image name
37 | try {
38 | const runtime = await detectContainerRuntime();
39 | await buildContainer(runtime, imageName);
40 | } catch (error) {
41 | if (error instanceof Error) {
42 | console.error(error.message);
43 | } else {
44 | console.error(error);
45 | }
46 | process.exit(1);
47 | }
48 | })();
49 |
--------------------------------------------------------------------------------
/visual-regression/src/detectDockerRuntime.ts:
--------------------------------------------------------------------------------
1 | import { $ } from 'execa';
2 |
3 | /**
4 | * Detects the available container runtime (podman or docker).
5 | * @returns {Promise} The name of the container runtime (`podman` or `docker`).
6 | * @throws {Error} If neither runtime is found.
7 | */
8 | export async function detectContainerRuntime(): Promise<'docker' | 'podman'> {
9 | try {
10 | await $`podman -v`;
11 | return 'podman';
12 | } catch {
13 | try {
14 | await $`docker -v`;
15 | return 'docker';
16 | } catch {
17 | throw new Error(
18 | 'Neither podman nor docker is installed. Please install one of them.',
19 | );
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/visual-regression/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "rootDir": ".",
5 | "outDir": "dist",
6 | "types": ["node"],
7 | "lib": ["ES2022", "DOM"],
8 | },
9 | "include": [
10 | "src/**/*",
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config';
2 |
3 | export default defineConfig({
4 | test: {
5 | coverage: {
6 | provider: 'v8',
7 | all: true,
8 | include: ['src/**/*.ts'],
9 | },
10 | },
11 | });
12 |
--------------------------------------------------------------------------------