You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@leafer/display-module

Package Overview
Dependencies
Maintainers
1
Versions
117
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@leafer/display-module - npm Package Compare versions

Comparing version
1.0.0-beta.12
to
1.0.0-beta.15
+19
types/index.d.ts
import { ILeafEventerModule, ILeafDataProxyModule, ILeafMatrixModule, ILeafBoundsModule, ILeafHitModule, ILeafRenderModule, ILeafMaskModule, IBranchRenderModule } from '@leafer/interface';
declare const LeafEventer: ILeafEventerModule;
declare const LeafDataProxy: ILeafDataProxyModule;
declare const LeafMatrix: ILeafMatrixModule;
declare const LeafBounds: ILeafBoundsModule;
declare const LeafHit: ILeafHitModule;
declare const LeafRender: ILeafRenderModule;
declare const LeafMask: ILeafMaskModule;
declare const BranchRender: IBranchRenderModule;
export { BranchRender, LeafBounds, LeafDataProxy, LeafEventer, LeafHit, LeafMask, LeafMatrix, LeafRender };
+7
-5
{
"name": "@leafer/display-module",
"version": "1.0.0-beta.12",
"version": "1.0.0-beta.15",
"description": "@leafer/display-module",

@@ -8,4 +8,6 @@ "author": "Chao (Leafer) Wan",

"main": "src/index.ts",
"types": "types/index.d.ts",
"files": [
"src"
"types",
"dist"
],

@@ -23,8 +25,8 @@ "repository": {

"dependencies": {
"@leafer/event": "1.0.0-beta.12",
"@leafer/math": "1.0.0-beta.12"
"@leafer/event": "1.0.0-beta.15",
"@leafer/math": "1.0.0-beta.15"
},
"devDependencies": {
"@leafer/interface": "1.0.0-beta.12"
"@leafer/interface": "1.0.0-beta.15"
}
}
import { ILeaf, ILeaferCanvas, IRenderOptions, IBranchRenderModule } from '@leafer/interface'
export const BranchRender: IBranchRenderModule = {
__updateChange(): void {
const { __layout: layout } = this
if (layout.childrenSortChanged) {
this.__updateSortChildren()
layout.childrenSortChanged = false
}
this.__.__checkSingle()
},
__render(canvas: ILeaferCanvas, options: IRenderOptions): void {
if (this.__worldOpacity) {
if (this.__.__single) {
canvas.resetTransform()
const tempCanvas = canvas.getSameCanvas()
this.__renderBranch(tempCanvas, options)
canvas.opacity = this.__worldOpacity
const blendMode = this.__.isEraser ? 'destination-out' : this.__.blendMode
options.matrix ? canvas.copyWorld(tempCanvas, null, null, blendMode) : canvas.copyWorld(tempCanvas, this.__world, this.__world, blendMode)
tempCanvas.recycle()
} else {
this.__renderBranch(canvas, options)
}
}
},
__renderBranch(canvas: ILeaferCanvas, options: IRenderOptions): void {
let child: ILeaf
const { children } = this
if (this.__hasMask && children.length > 1) {
let mask: boolean
let maskCanvas = canvas.getSameCanvas()
let contentCanvas = canvas.getSameCanvas()
for (let i = 0, len = children.length; i < len; i++) {
child = children[i]
if (child.isMask) {
if (mask) {
this.__renderMask(canvas, contentCanvas, maskCanvas)
maskCanvas.clear()
contentCanvas.clear()
} else {
mask = true
}
child.__render(maskCanvas, options)
continue
}
child.__render(contentCanvas, options)
}
this.__renderMask(canvas, contentCanvas, maskCanvas)
maskCanvas.recycle()
contentCanvas.recycle()
} else {
const { bounds, hideBounds } = options
for (let i = 0, len = children.length; i < len; i++) {
child = children[i]
if (bounds && !bounds.hit(child.__world, options.matrix)) continue
if (hideBounds && hideBounds.includes(child.__world, options.matrix)) continue
child.__render(canvas, options)
}
}
}
}
import { ILeafBoundsModule } from '@leafer/interface'
import { BoundsHelper } from '@leafer/math'
const { toOuterOf, copyAndSpread } = BoundsHelper
export const LeafBounds: ILeafBoundsModule = {
__updateWorldBounds(): void {
if (this.__layout.boundsChanged) {
let resize: boolean
const layout = this.__layout
if (layout.boxChanged) {
this.__updatePath()
this.__updateRenderPath()
this.__updateBoxBounds()
layout.boxChanged = false
resize = true
}
if (layout.localBoxChanged) { // position change
this.__updateLocalBoxBounds()
layout.localBoxChanged = false
if (layout.strokeSpread) layout.strokeChanged = true
if (layout.renderSpread) layout.renderChanged = true
this.parent?.__layout.boxChange()
}
if (layout.strokeChanged) {
layout.strokeSpread = this.__updateStrokeSpread()
if (layout.strokeSpread) {
if (layout.strokeBounds === layout.boxBounds) {
layout.spreadStroke()
}
this.__updateStrokeBounds()
this.__updateLocalStrokeBounds()
} else {
layout.spreadStrokeCancel()
}
layout.strokeChanged = false
if (layout.renderSpread) layout.renderChanged = true
if (this.parent) this.parent.__layout.strokeChange()
resize || (resize = true)
}
if (layout.renderChanged) {
layout.renderSpread = this.__updateRenderSpread()
if (layout.renderSpread) {
if (layout.renderBounds === layout.boxBounds || layout.renderBounds === layout.strokeBounds) {
layout.spreadRender()
}
this.__updateRenderBounds()
this.__updateLocalRenderBounds()
} else {
layout.spreadRenderCancel()
}
layout.renderChanged = false
if (this.parent) this.parent.__layout.renderChange()
}
layout.boundsChanged = false
toOuterOf(this.__layout.renderBounds, this.__world, this.__world)
if (resize) this.__onUpdateSize()
} else {
toOuterOf(this.__layout.renderBounds, this.__world, this.__world)
}
},
__updateLocalBoxBounds(): void {
toOuterOf(this.__layout.boxBounds, this.__local, this.__local)
},
__updateLocalStrokeBounds(): void {
toOuterOf(this.__layout.strokeBounds, this.__local, this.__layout.localStrokeBounds)
},
__updateLocalRenderBounds(): void {
toOuterOf(this.__layout.renderBounds, this.__local, this.__layout.localRenderBounds)
},
__updateBoxBounds(): void {
const b = this.__layout.boxBounds
b.x = 0
b.y = 0
b.width = this.__.width
b.height = this.__.height
},
__updateStrokeBounds(): void {
copyAndSpread(this.__layout.strokeBounds, this.__layout.boxBounds, this.__layout.strokeSpread)
},
__updateRenderBounds(): void {
copyAndSpread(this.__layout.renderBounds, this.__layout.strokeBounds, this.__layout.renderSpread)
},
}
import { ILeafDataProxyModule } from '@leafer/interface'
import { PropertyEvent } from '@leafer/event'
export const LeafDataProxy: ILeafDataProxyModule = {
__setAttr(name: string, newValue: unknown): void {
if (this.leafer && this.leafer.ready) {
this.__[name] = newValue
const { CHANGE } = PropertyEvent
const event = new PropertyEvent(CHANGE, this, name, this.__.__get(name), newValue)
if (this.hasEvent(CHANGE) && !this.isLeafer) this.emitEvent(event)
this.leafer.emitEvent(event)
} else {
this.__[name] = newValue
}
},
__getAttr(name: string): unknown {
return this.__.__get(name)
}
}
import { IEventListener, IEventListenerOptions, IEventListenerMap, IEventListenerItem, IEventListenerId, IEvent, IObject, IEventTarget, ILeafEventerModule } from '@leafer/interface'
const empty = {}
export const LeafEventer: ILeafEventerModule = {
on(type: string | string[], listener: IEventListener, options?: IEventListenerOptions | boolean): void {
let capture: boolean, once: boolean
if (options) {
if (typeof options === 'boolean') {
capture = options
} else {
capture = options.capture
once = options.once
}
}
let events: IEventListenerItem[]
const map = __getListenerMap(this, capture, true)
const typeList = typeof type === 'string' ? type.split(' ') : type
const item = once ? { listener, once } : { listener }
typeList.forEach(type => {
if (type) {
events = map[type]
if (events) {
if (events.findIndex(item => item.listener === listener) === -1) events.push(item)
} else {
map[type] = [item]
}
}
})
},
off(type: string | string[], listener: IEventListener, options?: IEventListenerOptions | boolean): void {
let capture: boolean
if (options) capture = typeof options === 'boolean' ? options : options.capture
let events: IEventListenerItem[], index: number
const map = __getListenerMap(this, capture)
const typeList = typeof type === 'string' ? type.split(' ') : type
typeList.forEach(type => {
if (type) {
events = map[type]
if (events) {
index = events.findIndex(item => item.listener === listener)
if (index > -1) events.splice(index, 1)
if (!events.length) delete map[type]
}
}
})
},
on_(type: string | string[], listener: IEventListener, bind?: IObject, options?: IEventListenerOptions | boolean): IEventListenerId {
if (bind) listener = listener.bind(bind)
this.on(type, listener, options)
return { type, listener, options }
},
off_(id: IEventListenerId | IEventListenerId[]): void {
if (!id) return
const list = id instanceof Array ? id : [id]
list.forEach(item => {
this.off(item.type, item.listener, item.options)
})
list.length = 0
},
once(type: string | string[], listener: IEventListener, capture?: boolean): void {
this.on(type, listener, { once: true, capture })
},
emit(type: string, event?: IEvent | IObject, capture?: boolean): void {
const map = __getListenerMap(this, capture)
const list = map[type]
if (list) {
let item: IEventListenerItem
for (let i = 0, len = list.length; i < len; i++) {
item = list[i]
item.listener(event)
if (item.once) {
this.off(type, item.listener, capture)
i--, len--
}
if (event && (event as IEvent).isStopNow) break
}
}
},
emitEvent(event: IEvent, capture?: boolean): void {
event.current = this
this.emit(event.type, event, capture)
},
hasEvent(type: string, capture?: boolean): boolean {
const { __bubbleMap: b, __captureMap: c } = this
if (capture === undefined) {
return !!((c && c[type]) || (b && b[type]))
} else {
return !!(capture ? (c && c[type]) : (b && b[type]))
}
},
}
function __getListenerMap(eventer: IEventTarget, capture?: boolean, create?: boolean): IEventListenerMap {
if (capture) {
const { __captureMap: c } = eventer
if (c) {
return c
} else {
return create ? eventer.__captureMap = {} : empty
}
} else {
const { __bubbleMap: b } = eventer
if (b) {
return b
} else {
return create ? eventer.__bubbleMap = {} : empty
}
}
}
import { ILeafHitModule, IRadiusPointData, ILeaferCanvas } from '@leafer/interface'
import { PointHelper } from '@leafer/math'
const { toInnerRadiusPointOf } = PointHelper
const inner = {} as IRadiusPointData
export const LeafHit: ILeafHitModule = {
__hitWorld(point: IRadiusPointData): boolean {
if (this.__layout.hitCanvasChanged || !this.__hitCanvas) {
this.__updateHitCanvas()
this.__layout.hitCanvasChanged = false
}
toInnerRadiusPointOf(point, this.__world, inner)
return this.__hit(inner)
},
__drawHitPath(canvas: ILeaferCanvas): void {
this.__drawRenderPath(canvas)
}
}
import { ILeaf, ILeaferCanvas, ILeafMaskModule } from '@leafer/interface'
export const LeafMask: ILeafMaskModule = {
__updateEraser(value?: boolean): void {
this.__hasEraser = value ? true : this.children.some(item => item.__.isEraser)
},
__updateMask(value?: boolean): void {
this.__hasMask = value ? true : this.children.some(item => item.__.isMask)
},
__renderMask(canvas: ILeaferCanvas, content: ILeaferCanvas, mask: ILeaferCanvas): void {
content.resetTransform()
content.useMask(mask)
canvas.resetTransform()
canvas.opacity = this.__worldOpacity
canvas.copyWorld(content)
},
__removeMask(child?: ILeaf): void {
if (child) {
child.isMask = false
this.remove(child)
} else {
const { children } = this
for (let i = 0, len = children.length; i < len; i++) {
child = children[i]
if (child.isMask) {
this.__removeMask(child)
len--, i--
}
}
}
}
}
import { ILeafMatrixModule } from '@leafer/interface'
import { OneRadian, MatrixHelper } from '@leafer/math'
const { sin, cos } = Math
const defaultWorld = { ...MatrixHelper.defaultMatrix, scaleX: 1, scaleY: 1 }
export const LeafMatrix: ILeafMatrixModule = {
__updateWorldMatrix(): void {
const pw = this.parent ? this.parent.__world : defaultWorld
const r = this.__local
const w = this.__world
if (this.__layout.matrixChanged) this.__updateLocalMatrix()
if (this.__layout.affectScaleOrRotation) {
w.a = r.a * pw.a + r.b * pw.c
w.b = r.a * pw.b + r.b * pw.d
w.c = r.c * pw.a + r.d * pw.c
w.d = r.c * pw.b + r.d * pw.d
w.e = r.e * pw.a + r.f * pw.c + pw.e
w.f = r.e * pw.b + r.f * pw.d + pw.f
w.scaleX = pw.scaleX * this.__.scaleX
w.scaleY = pw.scaleY * this.__.scaleY
} else {
w.a = pw.a
w.b = pw.b
w.c = pw.c
w.d = pw.d
w.e = r.e * pw.a + r.f * pw.c + pw.e
w.f = r.e * pw.b + r.f * pw.d + pw.f
w.scaleX = pw.scaleX
w.scaleY = pw.scaleY
}
},
__updateLocalMatrix(): void {
const r = this.__local
const layout = this.__layout
if (layout.affectScaleOrRotation) {
const { scaleX, scaleY } = this.__
if (layout.affectRotation) {
if (layout.scaleChanged || layout.rotationChanged) {
let { rotation, skewX, skewY } = this.__
if (rotation || skewX || skewY) {
rotation *= OneRadian
if (skewX) skewX *= OneRadian
if (skewY) skewY *= OneRadian
r.a = scaleX * cos(rotation + skewY)
r.b = scaleX * sin(rotation + skewY)
r.c = scaleY * -sin(rotation - skewX)
r.d = scaleY * cos(rotation - skewX)
} else {
r.a = scaleX
r.b = 0
r.c = 0
r.d = scaleY
layout.affectRotation = false
}
layout.scaleChanged = false
layout.rotationChanged = false
}
} else {
if (layout.scaleChanged) {
r.a = scaleX
r.d = scaleY
layout.scaleChanged = false
}
}
}
if (layout.positionChanged) {
r.e = this.__.x
r.f = this.__.y
layout.positionChanged = false
}
this.__layout.matrixChanged = false
}
}
import { ILeaferCanvas, IRenderOptions, ILeafRenderModule } from '@leafer/interface'
export const LeafRender: ILeafRenderModule = {
__render(canvas: ILeaferCanvas, options: IRenderOptions): void {
if (this.__worldOpacity) {
canvas.setWorld(this.__world, options.matrix)
canvas.opacity = this.__worldOpacity
if (this.__.__single) {
const tempCanvas = canvas.getSameCanvas(true)
this.__draw(tempCanvas, options)
const blendMode = this.__.isEraser ? 'destination-out' : this.__.blendMode
if (options.matrix) {
canvas.resetTransform()
canvas.copyWorld(tempCanvas, null, null, blendMode)
} else {
canvas.copyWorldToInner(tempCanvas, this.__world, this.__layout.renderBounds, blendMode)
}
tempCanvas.recycle()
} else {
this.__draw(canvas, options)
}
}
},
__updateWorldOpacity(): void {
this.__worldOpacity = this.__.visible ? (this.parent ? this.parent.__worldOpacity * this.__.opacity : this.__.opacity) : 0
if (this.__layout.opacityChanged) this.__layout.opacityChanged = false
}
}