packages/core/src/rendering/render-pipeline.ts (117 lines of code) (raw):
import { assert } from '@canvas-ui/assert'
import { Log } from '../foundation'
import type { RenderObject } from '.'
import { PaintingContext } from './painting-context'
export class RenderPipeline {
constructor(
private readonly onRequestVisualUpdate: () => void
) {
}
private _rootNode?: RenderObject | undefined
get rootNode() {
return this._rootNode
}
set rootNode(value: RenderObject | undefined) {
if (value === this._rootNode) {
return
}
this._rootNode?.detach()
this._rootNode = value
this._rootNode?.attach(this)
}
private paintDirtyObjects: RenderObject[] = []
private needsCompositingDirtyObjects: RenderObject[] = []
private layoutDirtyObjects: RenderObject[] = []
private enterFrameObjects: RenderObject[] = []
get debugPaintDirtyObjects() {
return this.paintDirtyObjects
}
get debugNeedsCompositingDirtyObjects() {
return this.needsCompositingDirtyObjects
}
get debugLayoutDirtyObjects() {
return this.layoutDirtyObjects
}
addEnterFrame(object: RenderObject) {
if (this.enterFrameObjects.indexOf(object) === -1) {
this.enterFrameObjects.push(object)
}
}
@Log({ disabled: true })
addLayoutDirty(object: RenderObject): void {
if (this.layoutDirtyObjects.indexOf(object) === -1) {
this.layoutDirtyObjects.push(object)
}
}
addNeedsCompositingDirty(object: RenderObject): void {
if (this.needsCompositingDirtyObjects.indexOf(object) === -1) {
this.needsCompositingDirtyObjects.push(object)
}
}
@Log({ disabled: true })
addPaintDirty(object: RenderObject): void {
if (this.paintDirtyObjects.indexOf(object) === -1) {
this.paintDirtyObjects.push(object)
}
}
requestVisualUpdate() {
this.onRequestVisualUpdate()
}
flushEnterFrame() {
const enterFrameObjects = this.enterFrameObjects
this.enterFrameObjects = []
const n = enterFrameObjects.length
for (let i = 0; i < n; i++) {
const object = enterFrameObjects[i]
object.enterFrame()
}
}
flushLayout() {
while (this.layoutDirtyObjects.length > 0) {
const dirtyObjects = this.layoutDirtyObjects
this.layoutDirtyObjects = []
dirtyObjects.sort((a, b) => {
return a.depth - b.depth // 从外层布局到内层
})
const n = dirtyObjects.length
for (let i = 0; i < n; i++) {
const object = dirtyObjects[i]
if (object._layoutDirty && object.owner === this) {
object.layoutAsBoundary()
}
}
}
}
flushNeedsCompositing() {
this.needsCompositingDirtyObjects.sort((a, b) => {
return a.depth - b.depth
})
const n = this.needsCompositingDirtyObjects.length
for (let i = 0; i < n; i++) {
const object = this.needsCompositingDirtyObjects[i]
if (object._needsCompositingDirty && object.owner === this) {
object.updateNeedsCompositing()
}
}
this.needsCompositingDirtyObjects = []
}
flushPaint() {
const dirtyObjects = this.paintDirtyObjects
this.paintDirtyObjects = []
dirtyObjects.sort((a, b) => {
return b.depth - a.depth // 从内层绘制到外层
})
const n = dirtyObjects.length
for (let i = 0; i < n; i++) {
const object = dirtyObjects[i]
if (object._paintDirty && object.owner === this) {
if (object._layer!.attached) {
PaintingContext.repaintCompositedChild(object)
} else {
object.skipPaint()
}
}
}
assert(this.paintDirtyObjects.length === 0, 'flushPaint 结束后仍有节点没有被绘制')
}
}