diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index c61026be..0552e971 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -17,8 +17,12 @@ jobs:
contents: read
pull-requests: write
steps:
- - uses: actions/checkout@v5
- - uses: actions/setup-node@v5
+ - uses: actions/checkout@v6
+ - uses: actions/setup-node@v6
+ with:
+ node-version: 24
+ registry-url: "https://registry.npmjs.org"
+ - run: npm install -g npm@latest
- run: npm install
- run: npm run test
@@ -28,7 +32,11 @@ jobs:
contents: read
pull-requests: write
steps:
- - uses: actions/checkout@v5
- - uses: actions/setup-node@v5
+ - uses: actions/checkout@v6
+ - uses: actions/setup-node@v6
+ with:
+ node-version: 24
+ registry-url: "https://registry.npmjs.org"
+ - run: npm install -g npm@latest
- run: npm install
- run: npm run test
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index b97d39af..b089ac53 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -17,8 +17,12 @@ jobs:
contents: read
pull-requests: write
steps:
- - uses: actions/checkout@v5
- - uses: actions/setup-node@v5
+ - uses: actions/checkout@v6
+ - uses: actions/setup-node@v6
+ with:
+ node-version: 24
+ registry-url: "https://registry.npmjs.org"
+ - run: npm install -g npm@latest
- run: npm install
- run: npm run lint
@@ -28,7 +32,11 @@ jobs:
contents: read
pull-requests: write
steps:
- - uses: actions/checkout@v5
- - uses: actions/setup-node@v5
+ - uses: actions/checkout@v6
+ - uses: actions/setup-node@v6
+ with:
+ node-version: 24
+ registry-url: "https://registry.npmjs.org"
+ - run: npm install -g npm@latest
- run: npm install
- run: npm run lint
\ No newline at end of file
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 37e85efa..95c1aa8f 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -12,11 +12,12 @@ jobs:
contents: read
pull-requests: write
steps:
- - uses: actions/checkout@v5
- - uses: actions/setup-node@v5
+ - uses: actions/checkout@v6
+ - uses: actions/setup-node@v6
with:
- node-version: "22.x"
+ node-version: 24
registry-url: "https://registry.npmjs.org"
+ - run: npm install -g npm@latest
- run: npm install
- run: npm run publish:dist
- run: cd ~/work/player/player/dist/src && npm publish --access public
diff --git a/.gitignore b/.gitignore
index c5695e03..c99f40d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,7 @@ build
coverage
.DS_Store
.idea
-Thumbs.db
\ No newline at end of file
+Thumbs.db
+.playwright-mcp
+playwright-report
+test-results
\ No newline at end of file
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 00000000..f1ad0ab1
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,130 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+
+Next2D Player is a WebGL/WebGPU-based 2D graphics rendering engine for creating rich, interactive graphics, games, and cross-platform applications. It uses hardware acceleration for graphics processing and OffscreenCanvas with web workers for multi-threaded rendering performance.
+
+## Build & Development Commands
+
+```bash
+npm install # Install dependencies
+npm start # Start dev server with Vite (opens index.html)
+npm test # Run all tests with Vitest
+npm run lint # ESLint for src/**/*.ts and packages/**/*.ts
+npm run build:vite # Build production bundle
+npm run clean # Clean build artifacts
+```
+
+### Running a Single Test
+
+Tests use Vitest. To run a specific test file:
+```bash
+npx vitest packages/webgl/src/Blend/service/BlendAddService.test.ts
+```
+
+Or run tests matching a pattern:
+```bash
+npx vitest --testNamePattern "BlendAddService"
+```
+
+## Architecture
+
+### Package Structure (Monorepo with npm workspaces)
+
+The `packages/` directory contains modular packages with strict dependency rules:
+
+**Core packages (loosely coupled, no cross-imports allowed):**
+- `@next2d/events` - Event system
+- `@next2d/cache` - Caching utilities
+- `@next2d/filters` - Image filters
+- `@next2d/geom` - Geometry/matrix utilities
+- `@next2d/texture-packer` - Texture atlas packing
+- `@next2d/render-queue` - Render command queue
+
+**Rendering layer:**
+- `@next2d/webgl` - WebGL rendering context and operations
+- `@next2d/webgpu` - WebGPU rendering (alternative backend)
+- `@next2d/renderer` - OffscreenCanvas worker-based renderer (imports only `@next2d/webgl`)
+
+**Display layer:**
+- `@next2d/display` - DisplayObject hierarchy (Shape, MovieClip, Bitmap, etc.)
+- `@next2d/text` - TextField rendering
+- `@next2d/media` - Audio/Video support
+- `@next2d/ui` - UI components
+- `@next2d/net` - Network/loading utilities
+
+**Entry point:**
+- `@next2d/core` - Main Next2D class, Player, Canvas (references other packages but cannot be referenced BY other packages)
+
+### Code Organization Pattern
+
+Each class follows a `usecase`/`service` pattern for method implementation:
+
+```
+class => method => service (simple operations)
+class => method => usecase => service (complex operations)
+```
+
+Key rules:
+- Logic lives in `usecase` or `service` files, not in class methods
+- Services cannot call other services directly
+- Usecases orchestrate multiple services
+- Methods only set class variables (`private`/`protected`)
+
+Directory structure example:
+```
+packages/webgl/src/
+ Context.ts # Main class
+ Context/
+ service/ContextResetService.ts # Simple operations
+ service/ContextResetService.test.ts
+ usecase/ContextBindUseCase.ts # Complex operations
+ usecase/ContextBindUseCase.test.ts
+```
+
+### Rendering Pipeline
+
+The player uses a two-thread architecture:
+1. **Main thread**: DisplayObject tree management, event handling, animation logic
+2. **Worker thread**: WebGL/WebGPU rendering via OffscreenCanvas
+
+Flow: DisplayObjects -> RenderQueue -> Worker -> WebGL Context -> Canvas
+
+Key rendering features:
+- Texture Atlas with binary tree packing for efficient GPU memory
+- Instanced array rendering for batch drawing
+- Filter/blend effects rendered to texture cache
+- Mask rendering with stencil buffer
+
+## WebGL/WebGPU Renderer Switching
+
+The renderer backend is controlled by the `useWebGPU` flag in:
+`packages/renderer/src/Command/service/CommandInitializeContextService.ts`
+
+- `const useWebGPU: boolean = true;` → WebGPU renderer
+- `const useWebGPU: boolean = false;` → WebGL renderer
+
+E2E tests use whichever renderer is set by this flag. To compare WebGL vs WebGPU output:
+1. Set `useWebGPU = false`, run e2e tests for WebGL snapshots
+2. Set `useWebGPU = true`, run e2e tests for WebGPU snapshots
+3. Compare the generated snapshots
+
+### E2E Tests
+
+E2E tests use Playwright. Run from the `e2e/` directory:
+```bash
+cd e2e
+npx playwright test tests/sprite.spec.ts --project=webgl --update-snapshots
+npx playwright test tests/sprite.spec.ts --project=webgpu --update-snapshots
+```
+
+Snapshots are saved to:
+- `e2e/snapshots/webgl/{spec}-snapshots/`
+- `e2e/snapshots/webgpu/{spec}-snapshots/`
+
+## Requirements
+
+- Node.js >= v22.x
+- TypeScript ES2020 target
diff --git a/drawing_flow_chart.svg b/drawing_flow_chart.svg
deleted file mode 100644
index 4f7b92b1..00000000
--- a/drawing_flow_chart.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/e2e/fixtures/images/test-asymmetric.png b/e2e/fixtures/images/test-asymmetric.png
new file mode 100644
index 00000000..781fd448
Binary files /dev/null and b/e2e/fixtures/images/test-asymmetric.png differ
diff --git a/e2e/fixtures/images/test-checker.png b/e2e/fixtures/images/test-checker.png
new file mode 100644
index 00000000..981c7948
Binary files /dev/null and b/e2e/fixtures/images/test-checker.png differ
diff --git a/e2e/fixtures/images/test-circle.png b/e2e/fixtures/images/test-circle.png
new file mode 100644
index 00000000..30a49686
Binary files /dev/null and b/e2e/fixtures/images/test-circle.png differ
diff --git a/e2e/fixtures/images/test-gradient.png b/e2e/fixtures/images/test-gradient.png
new file mode 100644
index 00000000..6b2b4fe4
Binary files /dev/null and b/e2e/fixtures/images/test-gradient.png differ
diff --git a/e2e/fixtures/images/test-star.png b/e2e/fixtures/images/test-star.png
new file mode 100644
index 00000000..2b8ff162
Binary files /dev/null and b/e2e/fixtures/images/test-star.png differ
diff --git a/e2e/fixtures/images/test-stripe.png b/e2e/fixtures/images/test-stripe.png
new file mode 100644
index 00000000..a927ac6c
Binary files /dev/null and b/e2e/fixtures/images/test-stripe.png differ
diff --git a/e2e/fixtures/videos/movie.mp4 b/e2e/fixtures/videos/movie.mp4
new file mode 100755
index 00000000..c09e412d
Binary files /dev/null and b/e2e/fixtures/videos/movie.mp4 differ
diff --git a/e2e/pages/blendmode/all-modes.html b/e2e/pages/blendmode/all-modes.html
new file mode 100644
index 00000000..6a122354
--- /dev/null
+++ b/e2e/pages/blendmode/all-modes.html
@@ -0,0 +1,490 @@
+
+
+
+
+
+ Next2D E2E - All BlendModes
+
+
+
+
+
+
+
diff --git a/e2e/pages/container/child-management.html b/e2e/pages/container/child-management.html
new file mode 100644
index 00000000..46b6bcd7
--- /dev/null
+++ b/e2e/pages/container/child-management.html
@@ -0,0 +1,146 @@
+
+
+
+
+
+ Next2D E2E - Container Child Management
+
+
+
+
+
+
+
diff --git a/e2e/pages/display-object/color-transform.html b/e2e/pages/display-object/color-transform.html
new file mode 100644
index 00000000..2ab40a06
--- /dev/null
+++ b/e2e/pages/display-object/color-transform.html
@@ -0,0 +1,108 @@
+
+
+
+
+
+ Next2D E2E - ColorTransform
+
+
+
+
+
+
+
diff --git a/e2e/pages/display-object/nested-transforms.html b/e2e/pages/display-object/nested-transforms.html
new file mode 100644
index 00000000..9a71662d
--- /dev/null
+++ b/e2e/pages/display-object/nested-transforms.html
@@ -0,0 +1,102 @@
+
+
+
+
+
+ Next2D E2E - Nested Transforms
+
+
+
+
+
+
+
diff --git a/e2e/pages/display-object/properties.html b/e2e/pages/display-object/properties.html
new file mode 100644
index 00000000..5c6f6da3
--- /dev/null
+++ b/e2e/pages/display-object/properties.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+ Next2D E2E - DisplayObject Properties
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/bevel.html b/e2e/pages/filter/bevel.html
new file mode 100644
index 00000000..22306911
--- /dev/null
+++ b/e2e/pages/filter/bevel.html
@@ -0,0 +1,136 @@
+
+
+
+
+
+ Next2D E2E - BevelFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/blur.html b/e2e/pages/filter/blur.html
new file mode 100644
index 00000000..2e34cc20
--- /dev/null
+++ b/e2e/pages/filter/blur.html
@@ -0,0 +1,64 @@
+
+
+
+
+
+ Next2D E2E - BlurFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/color-matrix.html b/e2e/pages/filter/color-matrix.html
new file mode 100644
index 00000000..2fb8dea3
--- /dev/null
+++ b/e2e/pages/filter/color-matrix.html
@@ -0,0 +1,289 @@
+
+
+
+
+
+ Next2D E2E - ColorMatrixFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/convolution.html b/e2e/pages/filter/convolution.html
new file mode 100644
index 00000000..9f145a1c
--- /dev/null
+++ b/e2e/pages/filter/convolution.html
@@ -0,0 +1,86 @@
+
+
+
+
+
+ Next2D E2E - ConvolutionFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/displacement.html b/e2e/pages/filter/displacement.html
new file mode 100644
index 00000000..90742b0e
--- /dev/null
+++ b/e2e/pages/filter/displacement.html
@@ -0,0 +1,320 @@
+
+
+
+
+
+ Next2D E2E - DisplacementMapFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/drop-shadow.html b/e2e/pages/filter/drop-shadow.html
new file mode 100644
index 00000000..f7a08dc7
--- /dev/null
+++ b/e2e/pages/filter/drop-shadow.html
@@ -0,0 +1,223 @@
+
+
+
+
+
+ Next2D E2E - DropShadowFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/filter-modes.html b/e2e/pages/filter/filter-modes.html
new file mode 100644
index 00000000..694915b9
--- /dev/null
+++ b/e2e/pages/filter/filter-modes.html
@@ -0,0 +1,156 @@
+
+
+
+
+
+ Next2D E2E - Filter Modes
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/filter-quality.html b/e2e/pages/filter/filter-quality.html
new file mode 100644
index 00000000..67881fdf
--- /dev/null
+++ b/e2e/pages/filter/filter-quality.html
@@ -0,0 +1,97 @@
+
+
+
+
+
+ Next2D E2E - Filter Quality
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/glow.html b/e2e/pages/filter/glow.html
new file mode 100644
index 00000000..0aff9883
--- /dev/null
+++ b/e2e/pages/filter/glow.html
@@ -0,0 +1,187 @@
+
+
+
+
+
+ Next2D E2E - GlowFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/gradient-bevel.html b/e2e/pages/filter/gradient-bevel.html
new file mode 100644
index 00000000..e7d15427
--- /dev/null
+++ b/e2e/pages/filter/gradient-bevel.html
@@ -0,0 +1,364 @@
+
+
+
+
+
+ Next2D E2E - GradientBevelFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/gradient-glow.html b/e2e/pages/filter/gradient-glow.html
new file mode 100644
index 00000000..ae374675
--- /dev/null
+++ b/e2e/pages/filter/gradient-glow.html
@@ -0,0 +1,434 @@
+
+
+
+
+
+ Next2D E2E - GradientGlowFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/filter/multi-filter.html b/e2e/pages/filter/multi-filter.html
new file mode 100644
index 00000000..43c14322
--- /dev/null
+++ b/e2e/pages/filter/multi-filter.html
@@ -0,0 +1,206 @@
+
+
+
+
+
+ Next2D E2E - MultiFilter
+
+
+
+
+
+
+
diff --git a/e2e/pages/mask/sprite-mask.html b/e2e/pages/mask/sprite-mask.html
new file mode 100644
index 00000000..1a970242
--- /dev/null
+++ b/e2e/pages/mask/sprite-mask.html
@@ -0,0 +1,626 @@
+
+
+
+
+
+ Next2D E2E - Sprite Mask
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/fill-bitmap.html b/e2e/pages/shape/fill-bitmap.html
new file mode 100644
index 00000000..e73c251f
--- /dev/null
+++ b/e2e/pages/shape/fill-bitmap.html
@@ -0,0 +1,150 @@
+
+
+
+
+
+ Next2D E2E - Fill Bitmap
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/fill-gradient.html b/e2e/pages/shape/fill-gradient.html
new file mode 100644
index 00000000..c69055ba
--- /dev/null
+++ b/e2e/pages/shape/fill-gradient.html
@@ -0,0 +1,227 @@
+
+
+
+
+
+ Next2D E2E - Fill Gradient
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/fill-solid.html b/e2e/pages/shape/fill-solid.html
new file mode 100644
index 00000000..eda61092
--- /dev/null
+++ b/e2e/pages/shape/fill-solid.html
@@ -0,0 +1,102 @@
+
+
+
+
+
+ Next2D E2E - Fill Solid
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/graphics-clear.html b/e2e/pages/shape/graphics-clear.html
new file mode 100644
index 00000000..985b0898
--- /dev/null
+++ b/e2e/pages/shape/graphics-clear.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+ Next2D E2E - Graphics Clear
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/graphics-clone.html b/e2e/pages/shape/graphics-clone.html
new file mode 100644
index 00000000..57e127ab
--- /dev/null
+++ b/e2e/pages/shape/graphics-clone.html
@@ -0,0 +1,86 @@
+
+
+
+
+
+ Next2D E2E - Graphics Clone
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/line-bitmap.html b/e2e/pages/shape/line-bitmap.html
new file mode 100644
index 00000000..b3a83d2d
--- /dev/null
+++ b/e2e/pages/shape/line-bitmap.html
@@ -0,0 +1,166 @@
+
+
+
+
+
+ Next2D E2E - Line Bitmap
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/line-gradient.html b/e2e/pages/shape/line-gradient.html
new file mode 100644
index 00000000..b968b35f
--- /dev/null
+++ b/e2e/pages/shape/line-gradient.html
@@ -0,0 +1,190 @@
+
+
+
+
+
+ Next2D E2E - Line Gradient
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/line-style.html b/e2e/pages/shape/line-style.html
new file mode 100644
index 00000000..a743683f
--- /dev/null
+++ b/e2e/pages/shape/line-style.html
@@ -0,0 +1,272 @@
+
+
+
+
+
+ Next2D E2E - Line Style
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/load-image-flip.html b/e2e/pages/shape/load-image-flip.html
new file mode 100644
index 00000000..8e8912ae
--- /dev/null
+++ b/e2e/pages/shape/load-image-flip.html
@@ -0,0 +1,101 @@
+
+
+
+
+
+ Next2D E2E - Shape Load Image Flip Test
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/load-image.html b/e2e/pages/shape/load-image.html
new file mode 100644
index 00000000..ac2a9dbf
--- /dev/null
+++ b/e2e/pages/shape/load-image.html
@@ -0,0 +1,283 @@
+
+
+
+
+
+ Next2D E2E - Shape Load Image
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/paths.html b/e2e/pages/shape/paths.html
new file mode 100644
index 00000000..725e3a66
--- /dev/null
+++ b/e2e/pages/shape/paths.html
@@ -0,0 +1,219 @@
+
+
+
+
+
+ Next2D E2E - Paths
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/scale9grid.html b/e2e/pages/shape/scale9grid.html
new file mode 100644
index 00000000..473d858a
--- /dev/null
+++ b/e2e/pages/shape/scale9grid.html
@@ -0,0 +1,199 @@
+
+
+
+
+
+ Next2D E2E - Scale9Grid
+
+
+
+
+
+
+
diff --git a/e2e/pages/shape/shapes.html b/e2e/pages/shape/shapes.html
new file mode 100644
index 00000000..cf2ab982
--- /dev/null
+++ b/e2e/pages/shape/shapes.html
@@ -0,0 +1,228 @@
+
+
+
+
+
+ Next2D E2E - Basic Shapes
+
+
+
+
+
+
+
diff --git a/e2e/pages/sprite/sprite-blend.html b/e2e/pages/sprite/sprite-blend.html
new file mode 100644
index 00000000..24e4484e
--- /dev/null
+++ b/e2e/pages/sprite/sprite-blend.html
@@ -0,0 +1,232 @@
+
+
+
+
+
+ Next2D E2E - Sprite BlendMode
+
+
+
+
+
+
+
diff --git a/e2e/pages/sprite/sprite-filter.html b/e2e/pages/sprite/sprite-filter.html
new file mode 100644
index 00000000..9dd43a23
--- /dev/null
+++ b/e2e/pages/sprite/sprite-filter.html
@@ -0,0 +1,129 @@
+
+
+
+
+
+ Next2D E2E - Sprite Filter
+
+
+
+
+
+
+
diff --git a/e2e/pages/sprite/sprite-nested-filter.html b/e2e/pages/sprite/sprite-nested-filter.html
new file mode 100644
index 00000000..170f2737
--- /dev/null
+++ b/e2e/pages/sprite/sprite-nested-filter.html
@@ -0,0 +1,582 @@
+
+
+
+
+
+ Next2D E2E - Sprite Nested Filter + ColorTransform
+
+
+
+
+
+
+
diff --git a/e2e/pages/sprite/video-in-sprite-test.html b/e2e/pages/sprite/video-in-sprite-test.html
new file mode 100644
index 00000000..1e66b52f
--- /dev/null
+++ b/e2e/pages/sprite/video-in-sprite-test.html
@@ -0,0 +1,194 @@
+
+
+
+
+
+ Next2D E2E - Video in Sprite Debug
+
+
+
+
+
+
+
diff --git a/e2e/pages/textfield/auto-font-size.html b/e2e/pages/textfield/auto-font-size.html
new file mode 100644
index 00000000..f22684a8
--- /dev/null
+++ b/e2e/pages/textfield/auto-font-size.html
@@ -0,0 +1,77 @@
+
+
+
+
+
+ Next2D E2E - TextField AutoFontSize
+
+
+
+
+
+
+
diff --git a/e2e/pages/textfield/basic.html b/e2e/pages/textfield/basic.html
new file mode 100644
index 00000000..70465eb3
--- /dev/null
+++ b/e2e/pages/textfield/basic.html
@@ -0,0 +1,262 @@
+
+
+
+
+
+ Next2D E2E - TextField Basic
+
+
+
+
+
+
+
diff --git a/e2e/pages/textfield/blendmode.html b/e2e/pages/textfield/blendmode.html
new file mode 100644
index 00000000..fe545e5e
--- /dev/null
+++ b/e2e/pages/textfield/blendmode.html
@@ -0,0 +1,510 @@
+
+
+
+
+
+ Next2D E2E - TextField BlendModes
+
+
+
+
+
+
+
diff --git a/e2e/pages/textfield/filter.html b/e2e/pages/textfield/filter.html
new file mode 100644
index 00000000..48b8bec8
--- /dev/null
+++ b/e2e/pages/textfield/filter.html
@@ -0,0 +1,855 @@
+
+
+
+
+
+ Next2D E2E - TextField Filters
+
+
+
+
+
+
+
diff --git a/e2e/pages/textfield/format.html b/e2e/pages/textfield/format.html
new file mode 100644
index 00000000..74081589
--- /dev/null
+++ b/e2e/pages/textfield/format.html
@@ -0,0 +1,388 @@
+
+
+
+
+
+ Next2D E2E - TextField Format
+
+
+
+
+
+
+
diff --git a/e2e/pages/textfield/multiple-textfields.html b/e2e/pages/textfield/multiple-textfields.html
new file mode 100644
index 00000000..656f418d
--- /dev/null
+++ b/e2e/pages/textfield/multiple-textfields.html
@@ -0,0 +1,152 @@
+
+
+
+
+
+ Next2D E2E - Multiple TextFields Test
+
+
+
+
+
+
+
diff --git a/e2e/pages/textfield/scroll.html b/e2e/pages/textfield/scroll.html
new file mode 100644
index 00000000..47ad70bc
--- /dev/null
+++ b/e2e/pages/textfield/scroll.html
@@ -0,0 +1,125 @@
+
+
+
+
+
+ Next2D E2E - TextField Scroll
+
+
+
+
+
+
+
diff --git a/e2e/pages/textfield/thickness.html b/e2e/pages/textfield/thickness.html
new file mode 100644
index 00000000..ff1d58f2
--- /dev/null
+++ b/e2e/pages/textfield/thickness.html
@@ -0,0 +1,115 @@
+
+
+
+
+
+ Next2D E2E - TextField Thickness
+
+
+
+
+
+
+
diff --git a/e2e/pages/video/blendmode.html b/e2e/pages/video/blendmode.html
new file mode 100644
index 00000000..b3775183
--- /dev/null
+++ b/e2e/pages/video/blendmode.html
@@ -0,0 +1,178 @@
+
+
+
+
+
+ Next2D E2E - Video BlendModes
+
+
+
+
+
+
+
diff --git a/e2e/pages/video/filter.html b/e2e/pages/video/filter.html
new file mode 100644
index 00000000..4a857a23
--- /dev/null
+++ b/e2e/pages/video/filter.html
@@ -0,0 +1,153 @@
+
+
+
+
+
+ Next2D E2E - Video Filters
+
+
+
+
+
+
+
diff --git a/e2e/pages/video/playback.html b/e2e/pages/video/playback.html
new file mode 100644
index 00000000..836ce31f
--- /dev/null
+++ b/e2e/pages/video/playback.html
@@ -0,0 +1,372 @@
+
+
+
+
+
+ Next2D E2E - Video Playback
+
+
+
+
+
+
+
diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts
new file mode 100644
index 00000000..b5873ec1
--- /dev/null
+++ b/e2e/playwright.config.ts
@@ -0,0 +1,80 @@
+import { defineConfig, devices } from "@playwright/test";
+
+/**
+ * E2Eテスト設定
+ *
+ * WebGL/WebGPUの描画はヘッド付きモードで正確に動作するため、
+ * 全テストはローカル環境でヘッド付きモードで実行することを推奨。
+ *
+ * スクリプト:
+ * - npm run test:e2e:local - 全テスト(WebGL + WebGPU)をヘッド付きで実行
+ * - npm run test:e2e:local:webgl - WebGLのみヘッド付きで実行
+ * - npm run test:e2e:local:webgpu - WebGPUのみヘッド付きで実行
+ * - npm run test:e2e:update - スナップショット更新
+ */
+
+const isCI = !!process.env.CI;
+// ヘッドレスモードを強制しない限り、常にヘッド付きで実行
+const forceHeadless = process.env.HEADLESS === "true";
+
+export default defineConfig({
+ "testDir": "./tests",
+ "fullyParallel": true,
+ "forbidOnly": isCI,
+ "retries": isCI ? 2 : 0,
+ "workers": isCI ? 1 : undefined,
+ "reporter": "html",
+ "timeout": 60000,
+ "expect": {
+ "toHaveScreenshot": {
+ "maxDiffPixels": 100,
+ "threshold": 0.1
+ }
+ },
+ "use": {
+ "baseURL": "http://localhost:5173",
+ "trace": "on-first-retry",
+ "video": "on-first-retry"
+ },
+ "projects": [
+ {
+ "name": "webgl",
+ "use": {
+ ...devices["Desktop Chrome"],
+ // デフォルトでヘッド付きモード(WebGLの正確な描画のため)
+ "headless": forceHeadless,
+ "launchOptions": {
+ "args": [
+ "--use-gl=angle",
+ "--use-angle=default",
+ "--autoplay-policy=no-user-gesture-required"
+ ]
+ }
+ },
+ "snapshotDir": "./snapshots/webgl"
+ },
+ {
+ "name": "webgpu",
+ "use": {
+ ...devices["Desktop Chrome"],
+ // WebGPUはヘッド付きモードが必須
+ "headless": forceHeadless,
+ "launchOptions": {
+ "args": [
+ "--enable-unsafe-webgpu",
+ "--enable-features=Vulkan",
+ "--autoplay-policy=no-user-gesture-required"
+ ]
+ }
+ },
+ "snapshotDir": "./snapshots/webgpu"
+ }
+ ],
+ "webServer": {
+ "command": "npm start",
+ "url": "http://localhost:5173",
+ "reuseExistingServer": !isCI,
+ "timeout": 120000,
+ "cwd": ".."
+ }
+});
diff --git a/e2e/snapshots/webgl/blendmode.spec.ts-snapshots/blendmode-all-webgl-darwin.png b/e2e/snapshots/webgl/blendmode.spec.ts-snapshots/blendmode-all-webgl-darwin.png
new file mode 100644
index 00000000..edf0131a
Binary files /dev/null and b/e2e/snapshots/webgl/blendmode.spec.ts-snapshots/blendmode-all-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/container.spec.ts-snapshots/container-child-management-webgl-darwin.png b/e2e/snapshots/webgl/container.spec.ts-snapshots/container-child-management-webgl-darwin.png
new file mode 100644
index 00000000..17ed842f
Binary files /dev/null and b/e2e/snapshots/webgl/container.spec.ts-snapshots/container-child-management-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/display-object.spec.ts-snapshots/display-object-color-transform-webgl-darwin.png b/e2e/snapshots/webgl/display-object.spec.ts-snapshots/display-object-color-transform-webgl-darwin.png
new file mode 100644
index 00000000..02264b3d
Binary files /dev/null and b/e2e/snapshots/webgl/display-object.spec.ts-snapshots/display-object-color-transform-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/display-object.spec.ts-snapshots/display-object-nested-transforms-webgl-darwin.png b/e2e/snapshots/webgl/display-object.spec.ts-snapshots/display-object-nested-transforms-webgl-darwin.png
new file mode 100644
index 00000000..532e42cc
Binary files /dev/null and b/e2e/snapshots/webgl/display-object.spec.ts-snapshots/display-object-nested-transforms-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/display-object.spec.ts-snapshots/display-object-properties-webgl-darwin.png b/e2e/snapshots/webgl/display-object.spec.ts-snapshots/display-object-properties-webgl-darwin.png
new file mode 100644
index 00000000..1cf39ef9
Binary files /dev/null and b/e2e/snapshots/webgl/display-object.spec.ts-snapshots/display-object-properties-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-bevel-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-bevel-webgl-darwin.png
new file mode 100644
index 00000000..3df3bd1f
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-bevel-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-blur-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-blur-webgl-darwin.png
new file mode 100644
index 00000000..1b821a2f
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-blur-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-color-matrix-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-color-matrix-webgl-darwin.png
new file mode 100644
index 00000000..e8806027
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-color-matrix-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-convolution-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-convolution-webgl-darwin.png
new file mode 100644
index 00000000..25143725
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-convolution-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-displacement-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-displacement-webgl-darwin.png
new file mode 100644
index 00000000..61219c55
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-displacement-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-drop-shadow-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-drop-shadow-webgl-darwin.png
new file mode 100644
index 00000000..0c35a0e8
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-drop-shadow-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-glow-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-glow-webgl-darwin.png
new file mode 100644
index 00000000..57b62d87
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-glow-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-gradient-bevel-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-gradient-bevel-webgl-darwin.png
new file mode 100644
index 00000000..ebfd90f3
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-gradient-bevel-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-gradient-glow-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-gradient-glow-webgl-darwin.png
new file mode 100644
index 00000000..8ea1c951
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-gradient-glow-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-modes-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-modes-webgl-darwin.png
new file mode 100644
index 00000000..b5d64651
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-modes-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-multi-filter-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-multi-filter-webgl-darwin.png
new file mode 100644
index 00000000..24b763bf
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-multi-filter-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-quality-webgl-darwin.png b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-quality-webgl-darwin.png
new file mode 100644
index 00000000..f519354e
Binary files /dev/null and b/e2e/snapshots/webgl/filter.spec.ts-snapshots/filter-quality-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/mask.spec.ts-snapshots/mask-sprite-webgl-darwin.png b/e2e/snapshots/webgl/mask.spec.ts-snapshots/mask-sprite-webgl-darwin.png
new file mode 100644
index 00000000..0f6267b8
Binary files /dev/null and b/e2e/snapshots/webgl/mask.spec.ts-snapshots/mask-sprite-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/fill-bitmap-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/fill-bitmap-webgl-darwin.png
new file mode 100644
index 00000000..d218c17e
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/fill-bitmap-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/fill-gradient-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/fill-gradient-webgl-darwin.png
new file mode 100644
index 00000000..d9f769b3
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/fill-gradient-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/fill-solid-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/fill-solid-webgl-darwin.png
new file mode 100644
index 00000000..472215ad
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/fill-solid-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/graphics-clear-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/graphics-clear-webgl-darwin.png
new file mode 100644
index 00000000..89368b62
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/graphics-clear-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/graphics-clone-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/graphics-clone-webgl-darwin.png
new file mode 100644
index 00000000..aad34ea1
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/graphics-clone-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/line-bitmap-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/line-bitmap-webgl-darwin.png
new file mode 100644
index 00000000..52e6299a
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/line-bitmap-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/line-gradient-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/line-gradient-webgl-darwin.png
new file mode 100644
index 00000000..01862e98
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/line-gradient-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/line-style-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/line-style-webgl-darwin.png
new file mode 100644
index 00000000..59f036f1
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/line-style-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/load-image-flip-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/load-image-flip-webgl-darwin.png
new file mode 100644
index 00000000..2cca07b8
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/load-image-flip-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/load-image-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/load-image-webgl-darwin.png
new file mode 100644
index 00000000..8222359e
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/load-image-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/paths-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/paths-webgl-darwin.png
new file mode 100644
index 00000000..c8ad72a8
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/paths-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/scale9grid-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/scale9grid-webgl-darwin.png
new file mode 100644
index 00000000..ad5e90bc
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/scale9grid-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/shape.spec.ts-snapshots/shapes-webgl-darwin.png b/e2e/snapshots/webgl/shape.spec.ts-snapshots/shapes-webgl-darwin.png
new file mode 100644
index 00000000..e8f91c81
Binary files /dev/null and b/e2e/snapshots/webgl/shape.spec.ts-snapshots/shapes-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/sprite.spec.ts-snapshots/sprite-blend-webgl-darwin.png b/e2e/snapshots/webgl/sprite.spec.ts-snapshots/sprite-blend-webgl-darwin.png
new file mode 100644
index 00000000..9c5fb8aa
Binary files /dev/null and b/e2e/snapshots/webgl/sprite.spec.ts-snapshots/sprite-blend-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/sprite.spec.ts-snapshots/sprite-filter-webgl-darwin.png b/e2e/snapshots/webgl/sprite.spec.ts-snapshots/sprite-filter-webgl-darwin.png
new file mode 100644
index 00000000..238786fa
Binary files /dev/null and b/e2e/snapshots/webgl/sprite.spec.ts-snapshots/sprite-filter-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/sprite.spec.ts-snapshots/sprite-nested-filter-webgl-darwin.png b/e2e/snapshots/webgl/sprite.spec.ts-snapshots/sprite-nested-filter-webgl-darwin.png
new file mode 100644
index 00000000..b8617507
Binary files /dev/null and b/e2e/snapshots/webgl/sprite.spec.ts-snapshots/sprite-nested-filter-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-auto-font-size-webgl-darwin.png b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-auto-font-size-webgl-darwin.png
new file mode 100644
index 00000000..8f79032a
Binary files /dev/null and b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-auto-font-size-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-basic-webgl-darwin.png b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-basic-webgl-darwin.png
new file mode 100644
index 00000000..89d2d6ac
Binary files /dev/null and b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-basic-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-blendmode-webgl-darwin.png b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-blendmode-webgl-darwin.png
new file mode 100644
index 00000000..6775bc97
Binary files /dev/null and b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-blendmode-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-filter-webgl-darwin.png b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-filter-webgl-darwin.png
new file mode 100644
index 00000000..79c05297
Binary files /dev/null and b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-filter-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-format-webgl-darwin.png b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-format-webgl-darwin.png
new file mode 100644
index 00000000..ced9469f
Binary files /dev/null and b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-format-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-multiple-webgl-darwin.png b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-multiple-webgl-darwin.png
new file mode 100644
index 00000000..2ba9c7d4
Binary files /dev/null and b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-multiple-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-scroll-webgl-darwin.png b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-scroll-webgl-darwin.png
new file mode 100644
index 00000000..1ed897e3
Binary files /dev/null and b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-scroll-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-thickness-webgl-darwin.png b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-thickness-webgl-darwin.png
new file mode 100644
index 00000000..77b2738f
Binary files /dev/null and b/e2e/snapshots/webgl/textfield.spec.ts-snapshots/textfield-thickness-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/video.spec.ts-snapshots/video-blendmode-webgl-darwin.png b/e2e/snapshots/webgl/video.spec.ts-snapshots/video-blendmode-webgl-darwin.png
new file mode 100644
index 00000000..d77acea8
Binary files /dev/null and b/e2e/snapshots/webgl/video.spec.ts-snapshots/video-blendmode-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/video.spec.ts-snapshots/video-filter-webgl-darwin.png b/e2e/snapshots/webgl/video.spec.ts-snapshots/video-filter-webgl-darwin.png
new file mode 100644
index 00000000..af751db4
Binary files /dev/null and b/e2e/snapshots/webgl/video.spec.ts-snapshots/video-filter-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgl/video.spec.ts-snapshots/video-playback-webgl-darwin.png b/e2e/snapshots/webgl/video.spec.ts-snapshots/video-playback-webgl-darwin.png
new file mode 100644
index 00000000..74e41f0c
Binary files /dev/null and b/e2e/snapshots/webgl/video.spec.ts-snapshots/video-playback-webgl-darwin.png differ
diff --git a/e2e/snapshots/webgpu/blendmode.spec.ts-snapshots/blendmode-all-webgpu-darwin.png b/e2e/snapshots/webgpu/blendmode.spec.ts-snapshots/blendmode-all-webgpu-darwin.png
new file mode 100644
index 00000000..e10a4087
Binary files /dev/null and b/e2e/snapshots/webgpu/blendmode.spec.ts-snapshots/blendmode-all-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/container.spec.ts-snapshots/container-child-management-webgpu-darwin.png b/e2e/snapshots/webgpu/container.spec.ts-snapshots/container-child-management-webgpu-darwin.png
new file mode 100644
index 00000000..17ed842f
Binary files /dev/null and b/e2e/snapshots/webgpu/container.spec.ts-snapshots/container-child-management-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/display-object.spec.ts-snapshots/display-object-color-transform-webgpu-darwin.png b/e2e/snapshots/webgpu/display-object.spec.ts-snapshots/display-object-color-transform-webgpu-darwin.png
new file mode 100644
index 00000000..02264b3d
Binary files /dev/null and b/e2e/snapshots/webgpu/display-object.spec.ts-snapshots/display-object-color-transform-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/display-object.spec.ts-snapshots/display-object-nested-transforms-webgpu-darwin.png b/e2e/snapshots/webgpu/display-object.spec.ts-snapshots/display-object-nested-transforms-webgpu-darwin.png
new file mode 100644
index 00000000..532e42cc
Binary files /dev/null and b/e2e/snapshots/webgpu/display-object.spec.ts-snapshots/display-object-nested-transforms-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/display-object.spec.ts-snapshots/display-object-properties-webgpu-darwin.png b/e2e/snapshots/webgpu/display-object.spec.ts-snapshots/display-object-properties-webgpu-darwin.png
new file mode 100644
index 00000000..1cf39ef9
Binary files /dev/null and b/e2e/snapshots/webgpu/display-object.spec.ts-snapshots/display-object-properties-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-bevel-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-bevel-webgpu-darwin.png
new file mode 100644
index 00000000..d5c70798
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-bevel-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-blur-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-blur-webgpu-darwin.png
new file mode 100644
index 00000000..c19008ad
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-blur-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-color-matrix-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-color-matrix-webgpu-darwin.png
new file mode 100644
index 00000000..4937d63c
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-color-matrix-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-convolution-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-convolution-webgpu-darwin.png
new file mode 100644
index 00000000..93a00f90
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-convolution-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-displacement-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-displacement-webgpu-darwin.png
new file mode 100644
index 00000000..3cb8c677
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-displacement-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-drop-shadow-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-drop-shadow-webgpu-darwin.png
new file mode 100644
index 00000000..27354c9d
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-drop-shadow-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-glow-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-glow-webgpu-darwin.png
new file mode 100644
index 00000000..5ba2e163
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-glow-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-gradient-bevel-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-gradient-bevel-webgpu-darwin.png
new file mode 100644
index 00000000..5c8ed83d
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-gradient-bevel-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-gradient-glow-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-gradient-glow-webgpu-darwin.png
new file mode 100644
index 00000000..e05ddd20
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-gradient-glow-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-modes-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-modes-webgpu-darwin.png
new file mode 100644
index 00000000..0b2cb269
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-modes-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-multi-filter-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-multi-filter-webgpu-darwin.png
new file mode 100644
index 00000000..fc3a910a
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-multi-filter-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-quality-webgpu-darwin.png b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-quality-webgpu-darwin.png
new file mode 100644
index 00000000..8962a4f6
Binary files /dev/null and b/e2e/snapshots/webgpu/filter.spec.ts-snapshots/filter-quality-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/mask.spec.ts-snapshots/mask-sprite-webgpu-darwin.png b/e2e/snapshots/webgpu/mask.spec.ts-snapshots/mask-sprite-webgpu-darwin.png
new file mode 100644
index 00000000..5c854810
Binary files /dev/null and b/e2e/snapshots/webgpu/mask.spec.ts-snapshots/mask-sprite-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/fill-bitmap-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/fill-bitmap-webgpu-darwin.png
new file mode 100644
index 00000000..ccac7aa6
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/fill-bitmap-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/fill-gradient-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/fill-gradient-webgpu-darwin.png
new file mode 100644
index 00000000..2dd9d515
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/fill-gradient-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/fill-solid-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/fill-solid-webgpu-darwin.png
new file mode 100644
index 00000000..472215ad
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/fill-solid-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/graphics-clear-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/graphics-clear-webgpu-darwin.png
new file mode 100644
index 00000000..a5f32871
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/graphics-clear-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/graphics-clone-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/graphics-clone-webgpu-darwin.png
new file mode 100644
index 00000000..01a09176
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/graphics-clone-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/line-bitmap-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/line-bitmap-webgpu-darwin.png
new file mode 100644
index 00000000..6517dd8a
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/line-bitmap-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/line-gradient-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/line-gradient-webgpu-darwin.png
new file mode 100644
index 00000000..6a035ddc
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/line-gradient-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/line-style-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/line-style-webgpu-darwin.png
new file mode 100644
index 00000000..94f05d8f
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/line-style-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/load-image-flip-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/load-image-flip-webgpu-darwin.png
new file mode 100644
index 00000000..6370efee
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/load-image-flip-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/load-image-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/load-image-webgpu-darwin.png
new file mode 100644
index 00000000..73fae52d
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/load-image-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/paths-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/paths-webgpu-darwin.png
new file mode 100644
index 00000000..fa3d6a19
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/paths-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/scale9grid-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/scale9grid-webgpu-darwin.png
new file mode 100644
index 00000000..9a3dcc24
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/scale9grid-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/shape.spec.ts-snapshots/shapes-webgpu-darwin.png b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/shapes-webgpu-darwin.png
new file mode 100644
index 00000000..8767e8b6
Binary files /dev/null and b/e2e/snapshots/webgpu/shape.spec.ts-snapshots/shapes-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/sprite.spec.ts-snapshots/sprite-blend-webgpu-darwin.png b/e2e/snapshots/webgpu/sprite.spec.ts-snapshots/sprite-blend-webgpu-darwin.png
new file mode 100644
index 00000000..02372242
Binary files /dev/null and b/e2e/snapshots/webgpu/sprite.spec.ts-snapshots/sprite-blend-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/sprite.spec.ts-snapshots/sprite-filter-webgpu-darwin.png b/e2e/snapshots/webgpu/sprite.spec.ts-snapshots/sprite-filter-webgpu-darwin.png
new file mode 100644
index 00000000..f1fedcf9
Binary files /dev/null and b/e2e/snapshots/webgpu/sprite.spec.ts-snapshots/sprite-filter-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/sprite.spec.ts-snapshots/sprite-nested-filter-webgpu-darwin.png b/e2e/snapshots/webgpu/sprite.spec.ts-snapshots/sprite-nested-filter-webgpu-darwin.png
new file mode 100644
index 00000000..0117db0a
Binary files /dev/null and b/e2e/snapshots/webgpu/sprite.spec.ts-snapshots/sprite-nested-filter-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-auto-font-size-webgpu-darwin.png b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-auto-font-size-webgpu-darwin.png
new file mode 100644
index 00000000..fe6290b5
Binary files /dev/null and b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-auto-font-size-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-basic-webgpu-darwin.png b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-basic-webgpu-darwin.png
new file mode 100644
index 00000000..577bb11f
Binary files /dev/null and b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-basic-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-blendmode-webgpu-darwin.png b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-blendmode-webgpu-darwin.png
new file mode 100644
index 00000000..b07792d7
Binary files /dev/null and b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-blendmode-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-filter-webgpu-darwin.png b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-filter-webgpu-darwin.png
new file mode 100644
index 00000000..0c4560a5
Binary files /dev/null and b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-filter-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-format-webgpu-darwin.png b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-format-webgpu-darwin.png
new file mode 100644
index 00000000..20623eed
Binary files /dev/null and b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-format-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-multiple-webgpu-darwin.png b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-multiple-webgpu-darwin.png
new file mode 100644
index 00000000..502d992b
Binary files /dev/null and b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-multiple-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-scroll-webgpu-darwin.png b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-scroll-webgpu-darwin.png
new file mode 100644
index 00000000..4448bb0b
Binary files /dev/null and b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-scroll-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-thickness-webgpu-darwin.png b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-thickness-webgpu-darwin.png
new file mode 100644
index 00000000..9113c4bb
Binary files /dev/null and b/e2e/snapshots/webgpu/textfield.spec.ts-snapshots/textfield-thickness-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/video.spec.ts-snapshots/video-blendmode-webgpu-darwin.png b/e2e/snapshots/webgpu/video.spec.ts-snapshots/video-blendmode-webgpu-darwin.png
new file mode 100644
index 00000000..8af8a8c9
Binary files /dev/null and b/e2e/snapshots/webgpu/video.spec.ts-snapshots/video-blendmode-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/video.spec.ts-snapshots/video-filter-webgpu-darwin.png b/e2e/snapshots/webgpu/video.spec.ts-snapshots/video-filter-webgpu-darwin.png
new file mode 100644
index 00000000..9dda5728
Binary files /dev/null and b/e2e/snapshots/webgpu/video.spec.ts-snapshots/video-filter-webgpu-darwin.png differ
diff --git a/e2e/snapshots/webgpu/video.spec.ts-snapshots/video-playback-webgpu-darwin.png b/e2e/snapshots/webgpu/video.spec.ts-snapshots/video-playback-webgpu-darwin.png
new file mode 100644
index 00000000..07f5c3a4
Binary files /dev/null and b/e2e/snapshots/webgpu/video.spec.ts-snapshots/video-playback-webgpu-darwin.png differ
diff --git a/e2e/tests/blendmode.spec.ts b/e2e/tests/blendmode.spec.ts
new file mode 100644
index 00000000..bc7d2600
--- /dev/null
+++ b/e2e/tests/blendmode.spec.ts
@@ -0,0 +1,11 @@
+import { test, expect } from "@playwright/test";
+import { waitForCanvas } from "./helpers/wait-for-render";
+
+test.describe("BlendModeテスト", () => {
+ test("全14種類のBlendMode", async ({ page }) => {
+ await page.goto("/e2e/pages/blendmode/all-modes.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("blendmode-all.png");
+ });
+});
diff --git a/e2e/tests/container.spec.ts b/e2e/tests/container.spec.ts
new file mode 100644
index 00000000..51744d3c
--- /dev/null
+++ b/e2e/tests/container.spec.ts
@@ -0,0 +1,11 @@
+import { test, expect } from "@playwright/test";
+import { waitForCanvas } from "./helpers/wait-for-render";
+
+test.describe("コンテナテスト", () => {
+ test("子オブジェクトの管理(z-order, addChildAt, setChildIndex, swap, remove)", async ({ page }) => {
+ await page.goto("/e2e/pages/container/child-management.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("container-child-management.png");
+ });
+});
diff --git a/e2e/tests/display-object.spec.ts b/e2e/tests/display-object.spec.ts
new file mode 100644
index 00000000..25dedec2
--- /dev/null
+++ b/e2e/tests/display-object.spec.ts
@@ -0,0 +1,25 @@
+import { test, expect } from "@playwright/test";
+import { waitForCanvas } from "./helpers/wait-for-render";
+
+test.describe("DisplayObjectテスト", () => {
+ test("プロパティ(visible, alpha, rotation, scale, 複合transform)", async ({ page }) => {
+ await page.goto("/e2e/pages/display-object/properties.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("display-object-properties.png");
+ });
+
+ test("ColorTransform(色乗算、色オフセット、alpha、親子累積)", async ({ page }) => {
+ await page.goto("/e2e/pages/display-object/color-transform.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("display-object-color-transform.png");
+ });
+
+ test("ネストされたtransform(scale, rotation, position, alphaの累積)", async ({ page }) => {
+ await page.goto("/e2e/pages/display-object/nested-transforms.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("display-object-nested-transforms.png");
+ });
+});
diff --git a/e2e/tests/filter.spec.ts b/e2e/tests/filter.spec.ts
new file mode 100644
index 00000000..3aa18e17
--- /dev/null
+++ b/e2e/tests/filter.spec.ts
@@ -0,0 +1,88 @@
+import { test, expect } from "@playwright/test";
+import { waitForCanvas } from "./helpers/wait-for-render";
+
+test.describe("Filterテスト", () => {
+ test("BlurFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/blur.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-blur.png");
+ });
+
+ test("DropShadowFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/drop-shadow.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-drop-shadow.png");
+ });
+
+ test("GlowFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/glow.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-glow.png");
+ });
+
+ test("BevelFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/bevel.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-bevel.png");
+ });
+
+ test("ColorMatrixFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/color-matrix.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-color-matrix.png");
+ });
+
+ test("ConvolutionFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/convolution.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-convolution.png");
+ });
+
+ test("DisplacementMapFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/displacement.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-displacement.png");
+ });
+
+ test("GradientBevelFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/gradient-bevel.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-gradient-bevel.png");
+ });
+
+ test("GradientGlowFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/gradient-glow.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-gradient-glow.png");
+ });
+
+ test("MultiFilter", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/multi-filter.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-multi-filter.png");
+ });
+
+ test("フィルターモード(inner, knockout, hideObject, type)", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/filter-modes.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-modes.png");
+ });
+
+ test("フィルター品質(quality 1, 2, 3比較)", async ({ page }) => {
+ await page.goto("/e2e/pages/filter/filter-quality.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("filter-quality.png");
+ });
+});
diff --git a/e2e/tests/helpers/renderer-switcher.ts b/e2e/tests/helpers/renderer-switcher.ts
new file mode 100644
index 00000000..ecbd872d
--- /dev/null
+++ b/e2e/tests/helpers/renderer-switcher.ts
@@ -0,0 +1,40 @@
+import { Page, TestInfo } from "@playwright/test";
+
+/**
+ * 現在のテストプロジェクト(レンダラー)を取得
+ */
+export function getCurrentRenderer(testInfo: TestInfo): "webgl" | "webgpu"
+{
+ return testInfo.project.name as "webgl" | "webgpu";
+}
+
+/**
+ * レンダラー固有のスナップショット名を生成
+ */
+export function getSnapshotName(baseName: string, testInfo: TestInfo): string
+{
+ const renderer = getCurrentRenderer(testInfo);
+ return `${baseName}-${renderer}.png`;
+}
+
+/**
+ * ページにレンダラー設定を注入
+ */
+export async function injectRendererConfig(page: Page, testInfo: TestInfo): Promise
+{
+ const renderer = getCurrentRenderer(testInfo);
+
+ await page.addInitScript((rendererType) => {
+ (window as any).__NEXT2D_RENDERER__ = rendererType;
+ }, renderer);
+}
+
+/**
+ * レンダラータイプに応じたNext2D設定を返す
+ */
+export function getNext2DConfig(testInfo: TestInfo): { renderer: string }
+{
+ return {
+ renderer: getCurrentRenderer(testInfo)
+ };
+}
diff --git a/e2e/tests/helpers/wait-for-render.ts b/e2e/tests/helpers/wait-for-render.ts
new file mode 100644
index 00000000..c31317d7
--- /dev/null
+++ b/e2e/tests/helpers/wait-for-render.ts
@@ -0,0 +1,56 @@
+import { Page } from "@playwright/test";
+
+/**
+ * 描画完了を待機するヘルパー関数
+ * Next2Dのレンダリングが完了するまで待機
+ */
+export async function waitForRender(page: Page, timeout: number = 10000): Promise
+{
+ // テストページで設定される __E2E_RENDER_COMPLETE__ フラグを待機
+ await page.waitForFunction(() => {
+ return (window as any).__E2E_RENDER_COMPLETE__ === true;
+ }, { timeout });
+
+ // ワーカースレッドでのレンダリング完了を待つため、より長い時間待機
+ await page.waitForTimeout(1000);
+
+ // 複数フレーム待機して描画が完全に安定することを確認
+ await page.evaluate(() => {
+ return new Promise((resolve) => {
+ let frameCount = 0;
+ const waitFrames = () => {
+ frameCount++;
+ if (frameCount >= 5) {
+ resolve();
+ } else {
+ requestAnimationFrame(waitFrames);
+ }
+ };
+ requestAnimationFrame(waitFrames);
+ });
+ });
+
+ // 追加の安定化待機
+ await page.waitForTimeout(500);
+}
+
+/**
+ * 特定の条件で描画完了を待機
+ */
+export async function waitForCondition(
+ page: Page,
+ condition: () => boolean | Promise,
+ timeout: number = 5000
+): Promise
+{
+ await page.waitForFunction(condition, { timeout });
+}
+
+/**
+ * Canvasが描画されるまで待機
+ */
+export async function waitForCanvas(page: Page, timeout: number = 30000): Promise
+{
+ await page.waitForSelector("canvas", { timeout });
+ await waitForRender(page, timeout);
+}
diff --git a/e2e/tests/mask.spec.ts b/e2e/tests/mask.spec.ts
new file mode 100644
index 00000000..363edab7
--- /dev/null
+++ b/e2e/tests/mask.spec.ts
@@ -0,0 +1,11 @@
+import { test, expect } from "@playwright/test";
+import { waitForCanvas } from "./helpers/wait-for-render";
+
+test.describe("Maskテスト", () => {
+ test("Sprite.mask(円形、矩形、星形、角丸、楕円、複雑なパス、Video、TextField)", async ({ page }) => {
+ await page.goto("/e2e/pages/mask/sprite-mask.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("mask-sprite.png");
+ });
+});
diff --git a/e2e/tests/shape.spec.ts b/e2e/tests/shape.spec.ts
new file mode 100644
index 00000000..59f1a75d
--- /dev/null
+++ b/e2e/tests/shape.spec.ts
@@ -0,0 +1,109 @@
+import { test, expect } from "@playwright/test";
+import { waitForCanvas } from "./helpers/wait-for-render";
+
+test.describe("Shape描画テスト", () => {
+ test.describe("Fill(塗り)", () => {
+ test("beginFill - 単色塗り", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/fill-solid.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("fill-solid.png");
+ });
+
+ test("beginGradientFill - グラデーション塗り", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/fill-gradient.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("fill-gradient.png");
+ });
+
+ test("beginBitmapFill - ビットマップ塗り", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/fill-bitmap.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("fill-bitmap.png");
+ });
+ });
+
+ test.describe("Line(線)", () => {
+ test("lineStyle - 線のスタイル(太さ、caps、joints)", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/line-style.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("line-style.png");
+ });
+
+ test("lineGradientStyle - グラデーション線", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/line-gradient.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("line-gradient.png");
+ });
+
+ test("lineBitmapStyle - ビットマップ線", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/line-bitmap.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("line-bitmap.png");
+ });
+ });
+
+ test.describe("図形", () => {
+ test("drawRect, drawRoundRect, drawCircle, drawEllipse", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/shapes.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("shapes.png");
+ });
+ });
+
+ test.describe("パス", () => {
+ test("moveTo, lineTo, curveTo, cubicCurveTo", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/paths.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("paths.png");
+ });
+ });
+
+ test.describe("scale9Grid", () => {
+ test("9スライススケーリング", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/scale9grid.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("scale9grid.png");
+ });
+ });
+
+ test.describe("画像読み込み", () => {
+ test("Shape.load - 画像読み込み(スケール、回転、BlendMode、Filter)", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/load-image.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("load-image.png");
+ });
+
+ test("Shape.load - 複数画像のY軸反転チェック", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/load-image-flip.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("load-image-flip.png");
+ });
+ });
+
+ test.describe("Graphics操作", () => {
+ test("clear() - クリア後の再描画", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/graphics-clear.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("graphics-clear.png");
+ });
+
+ test("copyFrom() - Graphicsのコピー", async ({ page }) => {
+ await page.goto("/e2e/pages/shape/graphics-clone.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("graphics-clone.png");
+ });
+ });
+});
diff --git a/e2e/tests/sprite.spec.ts b/e2e/tests/sprite.spec.ts
new file mode 100644
index 00000000..52637afe
--- /dev/null
+++ b/e2e/tests/sprite.spec.ts
@@ -0,0 +1,28 @@
+import { test, expect } from "@playwright/test";
+import { waitForCanvas } from "./helpers/wait-for-render";
+
+test.describe("Sprite テスト", () => {
+ test("Sprite Filter(コンテナフィルター)", async ({ page }) => {
+ await page.goto("/e2e/pages/sprite/sprite-filter.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("sprite-filter.png");
+ });
+
+ test("Sprite BlendMode(コンテナブレンド)", async ({ page }) => {
+ await page.goto("/e2e/pages/sprite/sprite-blend.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("sprite-blend.png");
+ });
+
+ test("Sprite ネストフィルター + ColorTransform", async ({ page }) => {
+ await page.goto("/e2e/pages/sprite/sprite-nested-filter.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("sprite-nested-filter.png", {
+ maxDiffPixelRatio: 0.025,
+ maxDiffPixels: 15000
+ });
+ });
+});
diff --git a/e2e/tests/textfield.spec.ts b/e2e/tests/textfield.spec.ts
new file mode 100644
index 00000000..465e3789
--- /dev/null
+++ b/e2e/tests/textfield.spec.ts
@@ -0,0 +1,60 @@
+import { test, expect } from "@playwright/test";
+import { waitForCanvas } from "./helpers/wait-for-render";
+
+test.describe("TextFieldテスト", () => {
+ test("基本テキスト(text, htmlText, autoSize, background, border)", async ({ page }) => {
+ await page.goto("/e2e/pages/textfield/basic.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("textfield-basic.png");
+ });
+
+ test("TextFormat(font, size, color, bold, italic, underline, align, leading, letterSpacing)", async ({ page }) => {
+ await page.goto("/e2e/pages/textfield/format.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("textfield-format.png");
+ });
+
+ test("TextFieldBlendMode(全14種類)", async ({ page }) => {
+ await page.goto("/e2e/pages/textfield/blendmode.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("textfield-blendmode.png");
+ });
+
+ test("TextFieldFilter(全フィルター)", async ({ page }) => {
+ await page.goto("/e2e/pages/textfield/filter.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("textfield-filter.png");
+ });
+
+ test("複数TextField - 全て表示されることを確認", async ({ page }) => {
+ await page.goto("/e2e/pages/textfield/multiple-textfields.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("textfield-multiple.png");
+ });
+
+ test("thickness(テキスト輪郭)", async ({ page }) => {
+ await page.goto("/e2e/pages/textfield/thickness.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("textfield-thickness.png");
+ });
+
+ test("scroll(scrollX, scrollY)", async ({ page }) => {
+ await page.goto("/e2e/pages/textfield/scroll.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("textfield-scroll.png");
+ });
+
+ test("autoFontSize(テキストサイズ自動調整)", async ({ page }) => {
+ await page.goto("/e2e/pages/textfield/auto-font-size.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("textfield-auto-font-size.png");
+ });
+});
diff --git a/e2e/tests/video.spec.ts b/e2e/tests/video.spec.ts
new file mode 100644
index 00000000..04e7f8a7
--- /dev/null
+++ b/e2e/tests/video.spec.ts
@@ -0,0 +1,25 @@
+import { test, expect } from "@playwright/test";
+import { waitForCanvas } from "./helpers/wait-for-render";
+
+test.describe("Videoテスト", () => {
+ test("動画表示(基本)", async ({ page }) => {
+ await page.goto("/e2e/pages/video/playback.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("video-playback.png");
+ });
+
+ test("動画BlendMode(全14種類)", async ({ page }) => {
+ await page.goto("/e2e/pages/video/blendmode.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("video-blendmode.png");
+ });
+
+ test("動画Filter(全フィルター)", async ({ page }) => {
+ await page.goto("/e2e/pages/video/filter.html");
+ await waitForCanvas(page);
+
+ await expect(page).toHaveScreenshot("video-filter.png");
+ });
+});
diff --git a/index.html b/index.html
index a593e24f..32f7d609 100644
--- a/index.html
+++ b/index.html
@@ -3,186 +3,61 @@
- Next2D
+ Next2D - BlendMode Test
-
+
-
\ No newline at end of file
+