@kurot/core 2.1.1 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +72 -0
- package/README.md +50 -2
- package/dist/kurot/display/DisplayObject.d.ts +2 -1
- package/dist/kurot/display/DisplayObject.d.ts.map +1 -1
- package/dist/kurot/display/DisplayObject.js.map +1 -1
- package/dist/kurot/player/canvas/CanvasRenderer.d.ts +2 -0
- package/dist/kurot/player/canvas/CanvasRenderer.d.ts.map +1 -1
- package/dist/kurot/player/canvas/CanvasRenderer.js +37 -1
- package/dist/kurot/player/canvas/CanvasRenderer.js.map +1 -1
- package/dist/kurot/player/pipes/BitmapTextPipe.d.ts +20 -0
- package/dist/kurot/player/pipes/BitmapTextPipe.d.ts.map +1 -0
- package/dist/kurot/player/pipes/BitmapTextPipe.js +27 -0
- package/dist/kurot/player/pipes/BitmapTextPipe.js.map +1 -0
- package/dist/kurot/player/pipes/index.d.ts +2 -0
- package/dist/kurot/player/pipes/index.d.ts.map +1 -1
- package/dist/kurot/player/pipes/index.js +1 -0
- package/dist/kurot/player/pipes/index.js.map +1 -1
- package/dist/kurot/player/webgl/WebGLRenderer.d.ts +1 -0
- package/dist/kurot/player/webgl/WebGLRenderer.d.ts.map +1 -1
- package/dist/kurot/player/webgl/WebGLRenderer.js +8 -0
- package/dist/kurot/player/webgl/WebGLRenderer.js.map +1 -1
- package/dist/kurot/resource/Resource.d.ts.map +1 -1
- package/dist/kurot/resource/Resource.js +4 -0
- package/dist/kurot/resource/Resource.js.map +1 -1
- package/dist/kurot/resource/ResourceItem.d.ts +1 -0
- package/dist/kurot/resource/ResourceItem.d.ts.map +1 -1
- package/dist/kurot/resource/ResourceItem.js +1 -0
- package/dist/kurot/resource/ResourceItem.js.map +1 -1
- package/dist/kurot/resource/analyzers/FontAnalyzer.d.ts +16 -0
- package/dist/kurot/resource/analyzers/FontAnalyzer.d.ts.map +1 -0
- package/dist/kurot/resource/analyzers/FontAnalyzer.js +75 -0
- package/dist/kurot/resource/analyzers/FontAnalyzer.js.map +1 -0
- package/dist/kurot/resource/analyzers/index.d.ts +1 -0
- package/dist/kurot/resource/analyzers/index.d.ts.map +1 -1
- package/dist/kurot/resource/analyzers/index.js +1 -0
- package/dist/kurot/resource/analyzers/index.js.map +1 -1
- package/dist/kurot/resource/index.d.ts +1 -0
- package/dist/kurot/resource/index.d.ts.map +1 -1
- package/dist/kurot/resource/index.js +1 -0
- package/dist/kurot/resource/index.js.map +1 -1
- package/dist/kurot/text/BitmapFont.d.ts +15 -21
- package/dist/kurot/text/BitmapFont.d.ts.map +1 -1
- package/dist/kurot/text/BitmapFont.js +59 -66
- package/dist/kurot/text/BitmapFont.js.map +1 -1
- package/dist/kurot/text/BitmapText.d.ts +29 -19
- package/dist/kurot/text/BitmapText.d.ts.map +1 -1
- package/dist/kurot/text/BitmapText.js +93 -141
- package/dist/kurot/text/BitmapText.js.map +1 -1
- package/dist/kurot/text/LineBreaks.d.ts +2 -1
- package/dist/kurot/text/LineBreaks.d.ts.map +1 -1
- package/dist/kurot/text/LineBreaks.js +13 -9
- package/dist/kurot/text/LineBreaks.js.map +1 -1
- package/dist/kurot/text/TextLineLayout.d.ts.map +1 -1
- package/dist/kurot/text/TextLineLayout.js +5 -12
- package/dist/kurot/text/TextLineLayout.js.map +1 -1
- package/dist/kurot/text/TextSegmentation.d.ts +7 -0
- package/dist/kurot/text/TextSegmentation.d.ts.map +1 -0
- package/dist/kurot/text/TextSegmentation.js +17 -0
- package/dist/kurot/text/TextSegmentation.js.map +1 -0
- package/dist/kurot/text/WordWrap.d.ts.map +1 -1
- package/dist/kurot/text/WordWrap.js +3 -11
- package/dist/kurot/text/WordWrap.js.map +1 -1
- package/dist/kurot/text/index.d.ts +1 -0
- package/dist/kurot/text/index.d.ts.map +1 -1
- package/dist/kurot/text/index.js.map +1 -1
- package/docs/ai-context.md +33 -9
- package/docs/architecture.md +332 -279
- package/docs/bitmap-fonts.md +85 -0
- package/docs/resource.md +185 -156
- package/docs/text-layout.md +71 -8
- package/package.json +4 -2
package/docs/architecture.md
CHANGED
|
@@ -1,228 +1,260 @@
|
|
|
1
|
-
# @kurot/core
|
|
1
|
+
# @kurot/core architecture
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> Package version: 2.2.1. See [CHANGELOG.md](../CHANGELOG.md) for release notes.
|
|
4
|
+
> The [AI context map](./ai-context.md) covers directories, non-obvious behavior,
|
|
5
|
+
> terminology and task-to-file references. This document explains design choices
|
|
6
|
+
> and internal mechanisms for contributors; the two documents complement each other.
|
|
5
7
|
|
|
6
8
|
---
|
|
7
9
|
|
|
8
|
-
##
|
|
9
|
-
|
|
10
|
-
`@kurot/core`
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
## 1. Overview
|
|
11
|
+
|
|
12
|
+
`@kurot/core` provides Kurot's display objects, rendering, events, geometry, text,
|
|
13
|
+
resources, networking and media runtime. Public APIs follow Egret's
|
|
14
|
+
`DisplayObject` and event model, while rendering uses a flat
|
|
15
|
+
`InstructionSet + RenderPipe` pipeline inspired by Pixi.js 8.
|
|
16
|
+
|
|
17
|
+
Since 2.2.0, Core uses published `@kurot/bitmap-font ^0.1.0` as the headless font-data
|
|
18
|
+
and layout kernel. Core manages font resources, image-page ownership and glyph
|
|
19
|
+
drawing in both backends. UI components belong to the UI package.
|
|
20
|
+
|
|
21
|
+
TextField uses Unicode 17.0 line-break rules with dictionary and overflow
|
|
22
|
+
tailoring. Since 2.2.1, tailoring uses imported rule identities, and layout
|
|
23
|
+
filters optional break positions through `Intl.Segmenter` grapheme boundaries.
|
|
24
|
+
Word and grapheme segmenters are cached; paragraph results remain local to
|
|
25
|
+
each layout. See [text layout](text-layout.md).
|
|
26
|
+
|
|
27
|
+
| Aspect | Description |
|
|
28
|
+
| ------------------ | ---------------------------------------------------------- |
|
|
29
|
+
| Modules | ES modules (`@kurot/core` npm package) |
|
|
30
|
+
| Types | Strict TypeScript (`strict: true`) |
|
|
31
|
+
| Target | ES2022 and modern browsers |
|
|
32
|
+
| Rendering | InstructionSet pipeline inspired by Pixi.js 8 |
|
|
33
|
+
| Batching | Multiple textures, up to 8 per batch |
|
|
34
|
+
| Package management | Independent pnpm package |
|
|
35
|
+
| Resources | Loading, caching and lifecycle management through Resource |
|
|
36
|
+
| WebGL | WebGL 1 and WebGL 2, selected at runtime |
|
|
37
|
+
|
|
38
|
+
See [Egret migration](../../../docs/egret-migration.md) for differences,
|
|
39
|
+
breaking changes and migration guidance.
|
|
24
40
|
|
|
25
41
|
---
|
|
26
42
|
|
|
27
|
-
##
|
|
43
|
+
## 2. Module structure
|
|
28
44
|
|
|
29
45
|
```
|
|
30
46
|
packages/core/src/kurot/
|
|
31
|
-
├── display/
|
|
32
|
-
│ ├── DisplayObject.ts
|
|
33
|
-
│ ├── DisplayObjectContainer.ts
|
|
34
|
-
│ ├── Bitmap.ts
|
|
35
|
-
│ ├── Sprite.ts
|
|
36
|
-
│ ├── Shape.ts
|
|
37
|
-
│ ├── Mesh.ts
|
|
38
|
-
│ ├── Stage.ts
|
|
39
|
-
│ ├── Graphics.ts
|
|
40
|
-
│ ├── GraphicsPath.ts
|
|
41
|
-
│ ├── enums/
|
|
42
|
-
│ └── texture/
|
|
43
|
-
├── player/
|
|
44
|
-
│ ├── Player.ts
|
|
45
|
-
│ ├── SystemTicker.ts
|
|
46
|
-
│ ├── RenderPipe.ts
|
|
47
|
-
│ ├──
|
|
48
|
-
│ ├──
|
|
49
|
-
│ ├──
|
|
50
|
-
│ ├──
|
|
51
|
-
│ ├──
|
|
52
|
-
│
|
|
53
|
-
│ │ ├──
|
|
54
|
-
│ │
|
|
55
|
-
│
|
|
56
|
-
│
|
|
57
|
-
│
|
|
58
|
-
│
|
|
59
|
-
│
|
|
60
|
-
│
|
|
61
|
-
│
|
|
62
|
-
│
|
|
63
|
-
│
|
|
64
|
-
│
|
|
65
|
-
│
|
|
66
|
-
│ ├──
|
|
67
|
-
│
|
|
68
|
-
│
|
|
69
|
-
│
|
|
70
|
-
│
|
|
71
|
-
│
|
|
72
|
-
│
|
|
73
|
-
│
|
|
74
|
-
│
|
|
75
|
-
│
|
|
76
|
-
│
|
|
77
|
-
|
|
78
|
-
├──
|
|
79
|
-
├──
|
|
80
|
-
├──
|
|
81
|
-
|
|
82
|
-
│ ├──
|
|
83
|
-
│ ├──
|
|
84
|
-
│ ├──
|
|
85
|
-
│ ├──
|
|
86
|
-
│ ├──
|
|
87
|
-
│ ├──
|
|
88
|
-
│ ├──
|
|
89
|
-
│ ├──
|
|
90
|
-
│ ├──
|
|
91
|
-
│ ├──
|
|
92
|
-
│
|
|
93
|
-
├──
|
|
94
|
-
│
|
|
95
|
-
|
|
96
|
-
│ ├──
|
|
97
|
-
│ ├──
|
|
98
|
-
│ ├──
|
|
99
|
-
│
|
|
100
|
-
├──
|
|
101
|
-
│ └──
|
|
102
|
-
├──
|
|
103
|
-
|
|
104
|
-
├──
|
|
105
|
-
|
|
106
|
-
├──
|
|
107
|
-
|
|
47
|
+
├── display/ # scene graph
|
|
48
|
+
│ ├── DisplayObject.ts # base class, dirty flags, render mode/type and cached bounds
|
|
49
|
+
│ ├── DisplayObjectContainer.ts # containers, render groups and zIndex sorting
|
|
50
|
+
│ ├── Bitmap.ts # bitmap display with scale9Grid
|
|
51
|
+
│ ├── Sprite.ts # container with Graphics
|
|
52
|
+
│ ├── Shape.ts # vector shapes
|
|
53
|
+
│ ├── Mesh.ts # vertices, indices and UVs
|
|
54
|
+
│ ├── Stage.ts # scene root
|
|
55
|
+
│ ├── Graphics.ts # vector drawing commands
|
|
56
|
+
│ ├── GraphicsPath.ts # PathCommandType and GraphicsCommand
|
|
57
|
+
│ ├── enums/ # BlendMode, BitmapFillMode, CapsStyle, GradientType, JointStyle, OrientationMode, StageScaleMode
|
|
58
|
+
│ └── texture/ # BitmapData, Texture, SpriteSheet, RenderTexture
|
|
59
|
+
├── player/ # rendering pipeline and game loop
|
|
60
|
+
│ ├── Player.ts # Stage/renderer integration and performance metrics
|
|
61
|
+
│ ├── SystemTicker.ts # RAF loop, ENTER_FRAME and callLater queue
|
|
62
|
+
│ ├── RenderPipe.ts # RenderPipe interface
|
|
63
|
+
│ ├── InstructionSet.ts # instruction list, renderableIndex and incremental dirty updates
|
|
64
|
+
│ ├── TouchHandler.ts # touch and mouse input
|
|
65
|
+
│ ├── ScreenAdapter.ts # screen adaptation with 7 scale modes
|
|
66
|
+
│ ├── createPlayer.ts # initialization and RenderTexture renderer setup
|
|
67
|
+
│ ├── KurotOptions.ts # player options
|
|
68
|
+
│ ├── pipes/ # RenderPipe implementations
|
|
69
|
+
│ │ ├── BitmapPipe.ts # bitmap instructions
|
|
70
|
+
│ │ ├── BitmapTextPipe.ts # native bitmap-font glyph instructions
|
|
71
|
+
│ │ ├── GraphicsPipe.ts # Canvas rasterization and texture upload
|
|
72
|
+
│ │ ├── MeshPipe.ts # mesh instructions
|
|
73
|
+
│ │ ├── FilterPipe.ts # pooled filter push/pop instructions
|
|
74
|
+
│ │ ├── MaskPipe.ts # pooled mask push/pop instructions
|
|
75
|
+
│ │ ├── TextPipe.ts # offscreen text rasterization and texture upload
|
|
76
|
+
│ │ └── ParticlePipe.ts # particle rendering
|
|
77
|
+
│ ├── canvas/ # Canvas 2D backend and offscreen capture
|
|
78
|
+
│ │ ├── CanvasRenderer.ts # direct traversal with built-in filter approximations
|
|
79
|
+
│ │ ├── DisplayList.ts # offscreen cache for cacheAsBitmap
|
|
80
|
+
│ │ └── CanvasBuffer.ts # Canvas buffers and pixel hit testing
|
|
81
|
+
│ └── webgl/ # primary WebGL backend
|
|
82
|
+
│ ├── WebGLRenderer.ts # build/execute phases and render groups
|
|
83
|
+
│ ├── WebGLRenderContext.ts # WebGL state, draw scheduling and filter execution
|
|
84
|
+
│ ├── WebGLRenderBuffer.ts # pooled offscreen, stencil and scissor buffers
|
|
85
|
+
│ ├── WebGLRenderTarget.ts # framebuffer management
|
|
86
|
+
│ ├── WebGLVertexArrayObject.ts # single-texture 20B and multi-texture 24B vertex layouts
|
|
87
|
+
│ ├── WebGLDrawCmdManager.ts # 12 draw command types, including MULTI_TEXTURE
|
|
88
|
+
│ ├── WebGLProgram.ts # shader program cache
|
|
89
|
+
│ ├── WebGLUtils.ts # shader compilation, program creation, tint and texture helpers
|
|
90
|
+
│ ├── MultiTextureBatcher.ts # 8-texture batches and slotMap assignments
|
|
91
|
+
│ └── shaders/ # GLSL sources
|
|
92
|
+
│ ├── ShaderLib.ts # GLSL ES 1.00 for WebGL 1
|
|
93
|
+
│ └── ShaderLib2.ts # GLSL ES 3.00 for WebGL 2
|
|
94
|
+
├── events/ # event classes, EventPhase and IEventDispatcher
|
|
95
|
+
├── geom/ # Matrix, Point, Rectangle
|
|
96
|
+
├── filters/ # Blur, Glow, DropShadow, ColorMatrix, CustomFilter, MultiPassFilter, BloomFilter
|
|
97
|
+
├── text/ # text data and layout
|
|
98
|
+
│ ├── TextField.ts # rich text, input mode and password display
|
|
99
|
+
│ ├── BitmapText.ts # bitmap text
|
|
100
|
+
│ ├── BitmapFont.ts # bitmap font and texture ownership
|
|
101
|
+
│ ├── StageText.ts # DOM input for INPUT mode
|
|
102
|
+
│ ├── HtmlTextParser.ts # HTML text parsing
|
|
103
|
+
│ ├── InputController.ts # selection, caret and keyboard input
|
|
104
|
+
│ ├── TextMeasurer.ts # measureText and getFontString
|
|
105
|
+
│ ├── TextSegmentation.ts # shared cached word/grapheme segmenters and UTF-16 boundaries
|
|
106
|
+
│ ├── LineBreaks.ts # Unicode 17.0 UAX #14 boundaries and dictionary segmentation
|
|
107
|
+
│ ├── TextLineLayout.ts # rich-text wrapping, width fitting and UTF-16 source offsets
|
|
108
|
+
│ ├── WordWrap.ts # independent token and grapheme utilities
|
|
109
|
+
│ ├── enums/ # HorizontalAlign, VerticalAlign, TextFieldType, TextFieldInputType
|
|
110
|
+
│ └── types/ # ITextElement, IWTextElement, ILineElement, IHitTextElement
|
|
111
|
+
├── resource/ # resource management
|
|
112
|
+
│ ├── Resource.ts # resource manager, shared instance and async/await API
|
|
113
|
+
│ ├── ResourceConfig.ts # resource configuration
|
|
114
|
+
│ ├── ResourceEvent.ts # resource events
|
|
115
|
+
│ ├── ResourceItem.ts # resource items
|
|
116
|
+
│ ├── ResourceLoader.ts # resource loading queue
|
|
117
|
+
│ └── analyzers/ # AnalyzerBase, Image, Json, Sheet, Sound, Text and Font analyzers
|
|
118
|
+
├── system/ # environment capabilities
|
|
119
|
+
│ └── Capabilities.ts # runtime capabilities using UA and Client Hints
|
|
120
|
+
├── net/ # HttpRequest, ImageLoader, HttpMethod, HttpResponseType
|
|
121
|
+
├── media/ # Sound, SoundChannel, Video
|
|
122
|
+
├── utils/ # ByteArray, Timer, Logger, FontManager, DebugLog, Base64Util, NumberUtils, toColorString
|
|
123
|
+
│ # object identity uses === or WeakMap; no HashObject
|
|
124
|
+
├── localStorage/ # local storage functions
|
|
125
|
+
└── external/ # ExternalInterface
|
|
108
126
|
```
|
|
109
127
|
|
|
110
128
|
---
|
|
111
129
|
|
|
112
|
-
##
|
|
130
|
+
## 3. Rendering pipeline
|
|
113
131
|
|
|
114
|
-
### 3.1
|
|
132
|
+
### 3.1 Build and execute phases
|
|
115
133
|
|
|
116
134
|
```
|
|
117
|
-
Phase A — Build
|
|
118
|
-
|
|
135
|
+
Phase A — Build (structureDirty):
|
|
136
|
+
Traverse the display tree → create Instructions with transform snapshots → InstructionSet
|
|
119
137
|
|
|
120
|
-
Phase A' — Update
|
|
121
|
-
|
|
138
|
+
Phase A' — Update (renderDirty):
|
|
139
|
+
Visit dirtyRenderables → refresh transform snapshots using renderableIndex lookups
|
|
122
140
|
|
|
123
|
-
Phase B — Execute
|
|
124
|
-
|
|
141
|
+
Phase B — Execute (every frame):
|
|
142
|
+
Dispatch instructions to pipes without traversing the scene graph
|
|
125
143
|
```
|
|
126
144
|
|
|
127
|
-
### 3.2 RenderPipe
|
|
145
|
+
### 3.2 RenderPipe
|
|
128
146
|
|
|
129
147
|
```
|
|
130
148
|
RenderPipe<T extends DisplayObject>
|
|
131
|
-
├── addToInstructionSet(renderable, set)
|
|
132
|
-
├── updateRenderable(renderable)
|
|
133
|
-
└── destroyRenderable(renderable)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
├── BitmapPipe
|
|
137
|
-
├──
|
|
138
|
-
├──
|
|
139
|
-
├──
|
|
140
|
-
├──
|
|
141
|
-
├──
|
|
142
|
-
|
|
149
|
+
├── addToInstructionSet(renderable, set) — build instructions after structure changes
|
|
150
|
+
├── updateRenderable(renderable) — update visual data
|
|
151
|
+
└── destroyRenderable(renderable) — optional immediate cleanup; see texture GC below
|
|
152
|
+
|
|
153
|
+
Implementations:
|
|
154
|
+
├── BitmapPipe → BitmapInstruction → drawImage(), including scale9Grid
|
|
155
|
+
├── BitmapTextPipe → BitmapTextInstruction → shared layout → batched glyph drawImage()
|
|
156
|
+
├── GraphicsPipe → GraphicsInstruction → Canvas rasterization → texture upload → drawTexture()
|
|
157
|
+
├── MeshPipe → MeshInstruction → drawMesh()
|
|
158
|
+
├── TextPipe → TextInstruction → offscreen Canvas → texture upload → drawImage()
|
|
159
|
+
├── ParticlePipe → ParticleInstruction → particle batches
|
|
160
|
+
├── FilterPipe → FilterPush/Pop → offscreen FBO → shader effects
|
|
161
|
+
└── MaskPipe → MaskPush/Pop → stencil, scissor or offscreen compositing
|
|
143
162
|
```
|
|
144
163
|
|
|
145
|
-
**GPU
|
|
164
|
+
**GPU texture cleanup.** `WebGLRenderer` does not automatically call
|
|
165
|
+
`destroyRenderable()`. Display objects have no permanent-destruction signal:
|
|
166
|
+
`$onRemoveFromStage` also fires when an object is temporarily removed and later
|
|
167
|
+
reused. Releasing textures at that point would force repeated rasterization and
|
|
168
|
+
uploads, for example when virtual lists reuse renderers.
|
|
146
169
|
|
|
147
|
-
|
|
170
|
+
GraphicsPipe and TextPipe use `FinalizationRegistry` to call `gl.deleteTexture()`
|
|
171
|
+
when their Graphics/TextField owners are garbage-collected. Explicit
|
|
172
|
+
`destroyRenderable()` remains an optional immediate-release path; it unregisters
|
|
173
|
+
the GC callback to avoid duplicate deletion. BitmapPipe and MeshPipe have no
|
|
174
|
+
pipe-owned texture cleanup because their textures belong to BitmapData.
|
|
175
|
+
|
|
176
|
+
### 3.3 Render groups
|
|
148
177
|
|
|
149
178
|
```typescript
|
|
150
179
|
backgroundLayer.isRenderGroup = true;
|
|
151
180
|
```
|
|
152
181
|
|
|
153
|
-
-
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
-
|
|
157
|
-
-
|
|
158
|
-
-
|
|
182
|
+
- Each render group owns an InstructionSet.
|
|
183
|
+
- Its parent set contains one `renderGroup` instruction referencing that subtree.
|
|
184
|
+
- Structure changes inside the group rebuild its own set, not its parent's set.
|
|
185
|
+
- Static subtrees do not need to be traversed on every WebGL frame.
|
|
186
|
+
- A `WeakMap<DisplayObjectContainer, InstructionSet>` stores group sets.
|
|
187
|
+
- WeakRef tracks group lifetimes without preventing garbage collection.
|
|
159
188
|
|
|
160
|
-
### 3.4
|
|
189
|
+
### 3.4 Multi-texture batching
|
|
161
190
|
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
|
|
165
|
-
-
|
|
166
|
-
-
|
|
191
|
+
- MultiTextureBatcher manages up to 8 texture slots, the WebGL 1 minimum guarantee.
|
|
192
|
+
- The multi-texture vertex layout adds `aTextureId`, increasing the stride from
|
|
193
|
+
20 to 24 bytes.
|
|
194
|
+
- The fragment shader selects textures with an if/else chain for WebGL 1 support.
|
|
195
|
+
- Mesh, filter and blend changes flush the current batch when needed.
|
|
196
|
+
- WebGLVertexArrayObject maintains single-texture and multi-texture buffers and
|
|
197
|
+
grows GPU buffers as needed.
|
|
167
198
|
|
|
168
|
-
### 3.5
|
|
199
|
+
### 3.5 Dirty flags
|
|
169
200
|
|
|
170
201
|
```
|
|
171
|
-
DisplayObject
|
|
172
|
-
├── cacheDirty
|
|
173
|
-
├── renderDirty
|
|
174
|
-
└── renderMode
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
├── $onStructureChange?: () => void
|
|
178
|
-
├── $onRenderableDirty?: (obj: DisplayObject) => void
|
|
179
|
-
├── DisplayObjectContainer.$onContainerStructureChange?: (owner) => void
|
|
202
|
+
DisplayObject flags:
|
|
203
|
+
├── cacheDirty — invalidates cacheAsBitmap and propagates upward
|
|
204
|
+
├── renderDirty — visual changes (position, texture, alpha, tint), propagated upward
|
|
205
|
+
└── renderMode — NONE, FILTER, CLIP or SCROLLRECT
|
|
206
|
+
|
|
207
|
+
Notifications (single-Player static hooks installed by Player):
|
|
208
|
+
├── $onStructureChange?: () => void — structure changes
|
|
209
|
+
├── $onRenderableDirty?: (obj: DisplayObject) => void — visual changes
|
|
210
|
+
├── DisplayObjectContainer.$onContainerStructureChange?: (owner) => void
|
|
180
211
|
├── $markDirty()
|
|
181
|
-
│ ├──
|
|
182
|
-
│ ├──
|
|
183
|
-
│ └──
|
|
212
|
+
│ ├── refresh worldAlpha/worldTint caches for constant-time reads
|
|
213
|
+
│ ├── $onRenderableDirty?.(this) → WebGLRenderer.markRenderableDirty()
|
|
214
|
+
│ └── propagate cacheDirty and renderDirty upward
|
|
184
215
|
├── $updateRenderMode()
|
|
185
|
-
│ └──
|
|
216
|
+
│ └── $onStructureChange?.() → WebGLRenderer.markStructureDirty()
|
|
186
217
|
└── DisplayObjectContainer.markDirtyInternal()
|
|
187
|
-
└──
|
|
218
|
+
└── $onContainerStructureChange?.(this) → markStructureDirty(owner)
|
|
188
219
|
```
|
|
189
220
|
|
|
190
|
-
|
|
191
|
-
|
|
221
|
+
The engine supports one Player per page. Its constructor assigns these static
|
|
222
|
+
hooks to instance closures, and `destroy()` clears them. See `player/Player.ts`.
|
|
192
223
|
|
|
193
|
-
### 3.6 RenderObjectType
|
|
224
|
+
### 3.6 RenderObjectType dispatch
|
|
194
225
|
|
|
195
|
-
|
|
226
|
+
DisplayObject uses the `renderObjectType` enum to avoid `instanceof` checks on
|
|
227
|
+
hot rendering paths:
|
|
196
228
|
|
|
197
|
-
|
|
|
198
|
-
|
|
|
199
|
-
| `NONE`
|
|
200
|
-
| `BITMAP`
|
|
201
|
-
| `MESH`
|
|
202
|
-
| `SHAPE`
|
|
203
|
-
| `SPRITE`
|
|
204
|
-
| `TEXT`
|
|
205
|
-
| `PARTICLE`
|
|
229
|
+
| Enum | Value | Display type | Pipe |
|
|
230
|
+
| ------------- | ----- | ------------ | -------------- |
|
|
231
|
+
| `NONE` | 0 | No rendering | — |
|
|
232
|
+
| `BITMAP` | 1 | Bitmap | BitmapPipe |
|
|
233
|
+
| `MESH` | 2 | Mesh | MeshPipe |
|
|
234
|
+
| `SHAPE` | 3 | Shape | GraphicsPipe |
|
|
235
|
+
| `SPRITE` | 4 | Sprite | GraphicsPipe |
|
|
236
|
+
| `TEXT` | 5 | TextField | TextPipe |
|
|
237
|
+
| `PARTICLE` | 6 | Particle | ParticlePipe |
|
|
238
|
+
| `BITMAP_TEXT` | 7 | BitmapText | BitmapTextPipe |
|
|
206
239
|
|
|
207
240
|
---
|
|
208
241
|
|
|
209
|
-
##
|
|
242
|
+
## 4. WebGL backend
|
|
210
243
|
|
|
211
|
-
### 4.1 WebGL
|
|
244
|
+
### 4.1 WebGL selection
|
|
212
245
|
|
|
213
|
-
|
|
246
|
+
WebGLRenderContext selects a backend during initialization:
|
|
214
247
|
|
|
215
|
-
- **WebGL 2
|
|
216
|
-
- **WebGL 1
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
`
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
- 着色器库通过实例属性动态绑定:`ctx.shaders`、`ctx.blurTierFn`、`ctx.makeBlurH`、`ctx.makeBlurV`
|
|
248
|
+
- **WebGL 2 first:** `canvas.getContext('webgl2')` uses ShaderLib2 (GLSL ES 3.00).
|
|
249
|
+
- **WebGL 1 fallback:** `canvas.getContext('webgl')` uses ShaderLib (GLSL ES 1.00).
|
|
250
|
+
No `experimental-webgl` alias is used; the target browsers support `webgl`.
|
|
251
|
+
- **No separate probe canvas:** Player tries WebGL 2 and WebGL 1 directly on the
|
|
252
|
+
application's canvas, then falls back to Canvas 2D if both fail.
|
|
253
|
+
`checkWebGLSupport()` remains available to callers but is not used by Player.
|
|
254
|
+
- Shader helpers are selected through context properties: `ctx.shaders`,
|
|
255
|
+
`ctx.blurTierFn`, `ctx.makeBlurH` and `ctx.makeBlurV`.
|
|
224
256
|
|
|
225
|
-
### 4.2
|
|
257
|
+
### 4.2 Rendering flow
|
|
226
258
|
|
|
227
259
|
```
|
|
228
260
|
Player.render()
|
|
@@ -231,77 +263,97 @@ Player.render()
|
|
|
231
263
|
→ Phase B: _executeInstructions()
|
|
232
264
|
→ Pipe.execute() → WebGLRenderContext.drawImage/drawMesh/drawTexture()
|
|
233
265
|
→ WebGLRenderContext.flush() → _flush()
|
|
234
|
-
→
|
|
266
|
+
→ upload vertices with bufferSubData → visit DrawCmdManager → dispatch draw batches
|
|
235
267
|
```
|
|
236
268
|
|
|
237
|
-
### 4.3
|
|
238
|
-
|
|
239
|
-
|
|
|
240
|
-
|
|
|
241
|
-
| default_vert + texture_frag
|
|
242
|
-
| multi_vert + multi_frag
|
|
243
|
-
| default_vert + colorTransform_frag
|
|
244
|
-
| default_vert + glow_frag
|
|
245
|
-
| fullscreen_vert + makeBlurH/
|
|
246
|
-
| default_vert + primitive_frag
|
|
247
|
-
| fullscreen_vert
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
`texture()`
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
- **
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
- **
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
-
|
|
269
|
+
### 4.3 Shaders
|
|
270
|
+
|
|
271
|
+
| Shader | Purpose | Source |
|
|
272
|
+
| ---------------------------------- | --------------------------------------- | --------- |
|
|
273
|
+
| default_vert + texture_frag | Standard texture drawing | ShaderLib |
|
|
274
|
+
| multi_vert + multi_frag | Multi-texture batches, up to 8 textures | ShaderLib |
|
|
275
|
+
| default_vert + colorTransform_frag | ColorMatrixFilter | ShaderLib |
|
|
276
|
+
| default_vert + glow_frag | Glow/DropShadow | ShaderLib |
|
|
277
|
+
| fullscreen_vert + makeBlurH/VFrag | Horizontal/vertical blur in two passes | ShaderLib |
|
|
278
|
+
| default_vert + primitive_frag | Solid rectangles for stencil masks | ShaderLib |
|
|
279
|
+
| fullscreen_vert | Fullscreen quad blits for filter passes | ShaderLib |
|
|
280
|
+
|
|
281
|
+
ShaderLib2 supplies equivalent GLSL ES 3.00 shaders for WebGL 2, using `in`/`out`
|
|
282
|
+
instead of `attribute`/`varying`, and `texture()` instead of `texture2D()`.
|
|
283
|
+
Blur shaders use fixed loop limits of 4, 8, 16 or 32 samples with triangular weights.
|
|
284
|
+
|
|
285
|
+
### 4.4 Filters
|
|
286
|
+
|
|
287
|
+
FilterPipe emits paired push/pop instructions:
|
|
288
|
+
|
|
289
|
+
- **Push:** allocate an offscreen FBO with filter padding and redirect drawing.
|
|
290
|
+
- **Pop:** call `compositeFilterResult()` to composite the result into the parent.
|
|
291
|
+
|
|
292
|
+
The compositing sequence is:
|
|
293
|
+
|
|
294
|
+
1. Flush pending drawing to complete the captured input.
|
|
295
|
+
2. WebGLFilterSystem executes filters in array order. Intermediate passes disable
|
|
296
|
+
blending, stencil and scissor and write to separate targets.
|
|
297
|
+
3. Restore the parent FBO, viewport and clip state explicitly.
|
|
298
|
+
4. Composite with `drawFramebufferTexture()` without applying inherited alpha/tint
|
|
299
|
+
a second time.
|
|
300
|
+
5. Flush and return intermediate textures to the pool. Failures release resources
|
|
301
|
+
and queued commands so a later frame can recover.
|
|
302
|
+
|
|
303
|
+
- **ColorMatrixFilter:** an unmasked leaf with one filter and inherited resolution
|
|
304
|
+
can use the inline path; groups and combinations use offscreen targets.
|
|
305
|
+
- **BlurFilter:** horizontal/vertical separation, with quality controlling pass
|
|
306
|
+
pairs. Large radii downsample to stay within the 32-physical-pixel shader tier.
|
|
307
|
+
- **Glow/DropShadow:** retain glow_frag; knockout controls whether the source image
|
|
308
|
+
remains in the output.
|
|
309
|
+
- **CustomFilter:** explicit GLSL 100/300 sources, reflected numeric uniforms and
|
|
310
|
+
auxiliary BitmapData uploads with independent sampling.
|
|
311
|
+
- **MultiPassFilter/BloomFilter:** ordered acyclic pass graphs, with original or
|
|
312
|
+
earlier inputs and per-pass scaling.
|
|
313
|
+
|
|
314
|
+
WebGLFilterTargetPool caches up to 16 idle targets or 64 MiB. Subtree captures and
|
|
315
|
+
auxiliary images are outside this limit. WebGLFilterTextures manages auxiliary
|
|
316
|
+
image uploads and restoration. Shader programs are cached by GL context and source.
|
|
317
|
+
|
|
318
|
+
Filter-chain padding accumulates and includes child effects without changing
|
|
319
|
+
layout bounds. Offscreen passes use framebuffer UVs, with (0,0) at the lower left,
|
|
320
|
+
and preserve orientation. DropShadow angles reach shaders in radians. Auxiliary
|
|
321
|
+
DOM image bindings use UV transforms to account for vertical orientation.
|
|
322
|
+
|
|
323
|
+
See [GPU filters](filters.md) for APIs, examples, Canvas support and cache limits.
|
|
324
|
+
|
|
325
|
+
### 4.5 Masks
|
|
326
|
+
|
|
327
|
+
- Axis-aligned scrollRect/maskRect without an outer scissor uses scissor clipping.
|
|
328
|
+
- Rotated rectangles or rectangles inside an outer scissor use stencil clipping.
|
|
329
|
+
Both the WebGL canvas and capability checks request stencil without depth.
|
|
330
|
+
- DisplayObject masks use offscreen compositing with destination-in.
|
|
287
331
|
|
|
288
332
|
---
|
|
289
333
|
|
|
290
|
-
##
|
|
334
|
+
## 5. Canvas 2D backend
|
|
335
|
+
|
|
336
|
+
CanvasRenderer traverses the scene graph directly and supplies the fallback when
|
|
337
|
+
WebGL is unavailable. It also rasterizes offscreen caches and RenderTexture captures.
|
|
291
338
|
|
|
292
|
-
|
|
339
|
+
- Offscreen Graphics caching through `canvasCacheDirty`.
|
|
340
|
+
- CSS blur/drop-shadow approximations for Blur, DropShadow and Glow.
|
|
341
|
+
- CPU pixel processing for ColorMatrixFilter.
|
|
342
|
+
- DisplayList support for cacheAsBitmap.
|
|
343
|
+
- Pixel hit testing through a 3×3 offscreen buffer.
|
|
344
|
+
- Bitmap, Shape, Sprite, Mesh, TextField and BitmapText rendering.
|
|
345
|
+
- BitmapText draws atlas regions from shared layout, including trim offsets, tint
|
|
346
|
+
and ordinary clipping. See [bitmap fonts](bitmap-fonts.md) for ownership.
|
|
347
|
+
- TextField measurement, line layout and fillText/strokeText drawing. See
|
|
348
|
+
[text layout](./text-layout.md) for wrapping and source-offset contracts.
|
|
293
349
|
|
|
294
|
-
|
|
295
|
-
-
|
|
296
|
-
|
|
297
|
-
- cacheAsBitmap 支持(通过 DisplayList)
|
|
298
|
-
- 像素级命中测试(3x3 离屏 buffer,hitTestBuffer 函数)
|
|
299
|
-
- 支持所有 DisplayObject 类型:Bitmap, Shape, Sprite, Mesh, TextField(含样式、对齐、自动换行)
|
|
300
|
-
- TextField 渲染:测量 → 分行 → Canvas 2D fillText/strokeText 绘制;断行规则与输入偏移契约见 [text-layout.md](./text-layout.md)
|
|
350
|
+
CustomFilter, MultiPassFilter and BloomFilter are GPU effects and are skipped.
|
|
351
|
+
Built-in Canvas approximations are not pixel-equivalent to WebGL. The same
|
|
352
|
+
boundary applies to cacheAsTexture and RenderTexture capture.
|
|
301
353
|
|
|
302
354
|
---
|
|
303
355
|
|
|
304
|
-
##
|
|
356
|
+
## 6. Application startup
|
|
305
357
|
|
|
306
358
|
### `createPlayer(options)`
|
|
307
359
|
|
|
@@ -319,55 +371,56 @@ const app = createPlayer({
|
|
|
319
371
|
app.start(root);
|
|
320
372
|
```
|
|
321
373
|
|
|
322
|
-
`createPlayer`
|
|
374
|
+
`createPlayer` initializes:
|
|
323
375
|
|
|
324
|
-
1.
|
|
325
|
-
2.
|
|
326
|
-
3.
|
|
327
|
-
4.
|
|
376
|
+
1. Capabilities._init() for OS, isMobile and language detection.
|
|
377
|
+
2. RenderTexture.renderer on first use, providing offscreen Canvas 2D rendering.
|
|
378
|
+
3. Stage, Player, TouchHandler and ScreenAdapter, preferring WebGL with Canvas fallback.
|
|
379
|
+
4. setupLifecycle(stage) for ENTER_FRAME and RENDER broadcasts.
|
|
328
380
|
|
|
329
381
|
### KurotOptions
|
|
330
382
|
|
|
331
|
-
|
|
|
332
|
-
| --------------- | ------------------- |
|
|
333
|
-
| `canvas` | `HTMLCanvasElement` |
|
|
334
|
-
| `frameRate` | `number` | `60`
|
|
335
|
-
| `scaleMode` | `StageScaleMode` | `'showAll'`
|
|
336
|
-
| `contentWidth` | `number` | `canvas.width`
|
|
337
|
-
| `contentHeight` | `number` | `canvas.height` |
|
|
338
|
-
| `resolution` | `number` | `min(DPR, 2)`
|
|
339
|
-
| `orientation` | `OrientationMode` | `'auto'`
|
|
340
|
-
| `maxTouches` | `number` | `99`
|
|
341
|
-
| `background` | `string` | —
|
|
342
|
-
|
|
343
|
-
### KurotApp
|
|
344
|
-
|
|
345
|
-
|
|
|
346
|
-
| --------------- |
|
|
347
|
-
| `player` | `Player`
|
|
348
|
-
| `stage` | `Stage`
|
|
349
|
-
| `touchHandler` | `TouchHandler`
|
|
350
|
-
| `screenAdapter` | `ScreenAdapter`
|
|
351
|
-
| `start(root?)` | `() => void`
|
|
352
|
-
| `stop()` | `() => void`
|
|
383
|
+
| Property | Type | Default | Description |
|
|
384
|
+
| --------------- | ------------------- | ------------------------- | --------------------------- |
|
|
385
|
+
| `canvas` | `HTMLCanvasElement` | Required | Rendering canvas |
|
|
386
|
+
| `frameRate` | `number` | `60` | Target frame rate |
|
|
387
|
+
| `scaleMode` | `StageScaleMode` | `'showAll'` | Screen scale mode |
|
|
388
|
+
| `contentWidth` | `number` | `canvas.width` or `640` | Logical content width |
|
|
389
|
+
| `contentHeight` | `number` | `canvas.height` or `1136` | Logical content height |
|
|
390
|
+
| `resolution` | `number` | `min(DPR, 2)` | Backing-store pixel density |
|
|
391
|
+
| `orientation` | `OrientationMode` | `'auto'` | Screen orientation |
|
|
392
|
+
| `maxTouches` | `number` | `99` | Maximum touch points |
|
|
393
|
+
| `background` | `string` | — | CSS background color |
|
|
394
|
+
|
|
395
|
+
### KurotApp
|
|
396
|
+
|
|
397
|
+
| Property | Type | Description |
|
|
398
|
+
| --------------- | -------------------------------- | ------------------------------------------------------ |
|
|
399
|
+
| `player` | `Player` | Renderer and game loop |
|
|
400
|
+
| `stage` | `Stage` | Scene root |
|
|
401
|
+
| `touchHandler` | `TouchHandler` | Touch and mouse input |
|
|
402
|
+
| `screenAdapter` | `ScreenAdapter` | Screen adaptation |
|
|
403
|
+
| `start(root?)` | `(root?: DisplayObject) => void` | Start or resume the game loop |
|
|
404
|
+
| `stop()` | `() => void` | Stop the loop; it can be resumed |
|
|
405
|
+
| `destroy()` | `() => void` | Release the player, input, adapter and lifecycle hooks |
|
|
353
406
|
|
|
354
407
|
---
|
|
355
408
|
|
|
356
|
-
##
|
|
357
|
-
|
|
358
|
-
`test
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
|
362
|
-
|
|
|
363
|
-
| events/
|
|
364
|
-
| geom/
|
|
365
|
-
| utils/
|
|
366
|
-
| display/
|
|
367
|
-
| filters/
|
|
368
|
-
| media/
|
|
369
|
-
| player/
|
|
370
|
-
| net/
|
|
371
|
-
| resource/
|
|
372
|
-
| examples/benchmark/tests/ |
|
|
373
|
-
| text/
|
|
409
|
+
## 7. Test coverage
|
|
410
|
+
|
|
411
|
+
Tests are organized by module in `test/`. Run `pnpm --dir packages/core test` for
|
|
412
|
+
current file and test counts.
|
|
413
|
+
|
|
414
|
+
| Module | Main coverage |
|
|
415
|
+
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
416
|
+
| events/ | Event, EventDispatcher, EventPropagation, EventMap, TouchEvent, HTTPStatusEvent, ProgressEvent |
|
|
417
|
+
| geom/ | Matrix, Point, Rectangle |
|
|
418
|
+
| utils/ | ByteArray, Base64Util, Logger, DebugLog, NumberUtils, toColorString |
|
|
419
|
+
| display/ | DisplayObject, DisplayObjectContainer, DisplayObjectIntegration, Bitmap, BitmapData, Sprite, Shape, Mesh, Stage, StageText, Graphics, Texture, SpriteSheet, BlendMode, DisplayList |
|
|
420
|
+
| filters/ | Filter classes, CustomFilter, filter integration and offscreen effect transforms |
|
|
421
|
+
| media/ | Sound, SoundChannel, Video |
|
|
422
|
+
| player/ | InstructionSet, InstructionPool, RenderGroup, TextPipe, MaskPipe, WebGLRendererDirty, WebGLRendererLeaf, WebGLVertexArrayObject, WebGLRenderBuffer, WebGLBlurFramebufferPool, CreatePlayer, TouchHandler |
|
|
423
|
+
| net/ | HttpRequest, ImageLoader |
|
|
424
|
+
| resource/ | Resource group serialization; ResourceLoader concurrency, retries and missing analyzers; FontAnalyzer loading and ownership |
|
|
425
|
+
| examples/benchmark/tests/ | Benchmark runtime and cross-engine comparisons |
|
|
426
|
+
| text/ | Display integration, BitmapText layout and native glyph geometry |
|