@leafer-ui/paint 1.0.0-rc.3 → 1.0.0-rc.30
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/package.json +6 -5
- package/src/Compute.ts +24 -23
- package/src/Fill.ts +4 -4
- package/src/Shape.ts +24 -24
- package/src/Stroke.ts +32 -23
- package/src/StrokeText.ts +19 -14
- package/src/index.ts +21 -7
- package/types/index.d.ts +3 -19
- package/src/paint/conic.ts +0 -48
- package/src/paint/image/check.ts +0 -49
- package/src/paint/image/data.ts +0 -43
- package/src/paint/image/image.ts +0 -77
- package/src/paint/image/index.ts +0 -4
- package/src/paint/image/mode.ts +0 -62
- package/src/paint/image/pattern.ts +0 -82
- package/src/paint/image/recycle.ts +0 -41
- package/src/paint/linear.ts +0 -33
- package/src/paint/radial.ts +0 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer-ui/paint",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.30",
|
|
4
4
|
"description": "@leafer-ui/paint",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,17 +15,18 @@
|
|
|
15
15
|
"type": "git",
|
|
16
16
|
"url": "https://github.com/leaferjs/ui.git"
|
|
17
17
|
},
|
|
18
|
-
"homepage": "https://github.com/leaferjs/ui/tree/main/packages/paint",
|
|
18
|
+
"homepage": "https://github.com/leaferjs/ui/tree/main/packages/partner/paint",
|
|
19
19
|
"bugs": "https://github.com/leaferjs/ui/issues",
|
|
20
20
|
"keywords": [
|
|
21
21
|
"leafer-ui",
|
|
22
22
|
"leaferjs"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@leafer/core": "1.0.0-rc.
|
|
25
|
+
"@leafer/core": "1.0.0-rc.30",
|
|
26
|
+
"@leafer-ui/draw": "1.0.0-rc.30"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
|
-
"@leafer/interface": "1.0.0-rc.
|
|
29
|
-
"@leafer-ui/interface": "1.0.0-rc.
|
|
29
|
+
"@leafer/interface": "1.0.0-rc.30",
|
|
30
|
+
"@leafer-ui/interface": "1.0.0-rc.30"
|
|
30
31
|
}
|
|
31
32
|
}
|
package/src/Compute.ts
CHANGED
|
@@ -1,34 +1,35 @@
|
|
|
1
|
-
import { IUI, IPaint, ILeafPaint, IRGB, IBooleanMap } from '@leafer-ui/interface'
|
|
2
|
-
import { ColorConvert } from '@leafer-ui/
|
|
3
|
-
|
|
4
|
-
import { image } from "./paint/image/image"
|
|
5
|
-
import { linearGradient } from './paint/linear'
|
|
6
|
-
import { radialGradient } from "./paint/radial"
|
|
7
|
-
import { conicGradient } from "./paint/conic"
|
|
8
|
-
import { recycleImage } from './paint/image'
|
|
1
|
+
import { IUI, IPaint, ILeafPaint, IRGB, IBooleanMap, IObject, IPaintAttr } from '@leafer-ui/interface'
|
|
2
|
+
import { ColorConvert, PaintImage, PaintGradient } from '@leafer-ui/draw'
|
|
9
3
|
|
|
10
4
|
|
|
11
5
|
let recycleMap: IBooleanMap
|
|
12
6
|
|
|
13
|
-
export function compute(
|
|
14
|
-
const
|
|
15
|
-
let item: ILeafPaint
|
|
16
|
-
let paints = ui.__.__input[attrName] as IPaint[]
|
|
7
|
+
export function compute(attrName: IPaintAttr, ui: IUI): void {
|
|
8
|
+
const data = ui.__, leafPaints: ILeafPaint[] = []
|
|
17
9
|
|
|
10
|
+
let paints: IPaint[] = data.__input[attrName], hasOpacityPixel: boolean
|
|
18
11
|
if (!(paints instanceof Array)) paints = [paints]
|
|
19
12
|
|
|
20
|
-
recycleMap = recycleImage(
|
|
13
|
+
recycleMap = PaintImage.recycleImage(attrName, data)
|
|
21
14
|
|
|
22
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
23
|
-
item = getLeafPaint(
|
|
24
|
-
if (item)
|
|
15
|
+
for (let i = 0, len = paints.length, item: ILeafPaint; i < len; i++) {
|
|
16
|
+
item = getLeafPaint(attrName, paints[i], ui)
|
|
17
|
+
if (item) leafPaints.push(item)
|
|
25
18
|
}
|
|
26
19
|
|
|
27
|
-
|
|
20
|
+
(data as IObject)['_' + attrName] = leafPaints.length ? leafPaints : undefined
|
|
21
|
+
|
|
22
|
+
if (leafPaints.length && leafPaints[0].image) hasOpacityPixel = leafPaints[0].image.hasOpacityPixel
|
|
23
|
+
|
|
24
|
+
if (attrName === 'fill') {
|
|
25
|
+
data.__pixelFill = hasOpacityPixel
|
|
26
|
+
} else {
|
|
27
|
+
data.__pixelStroke = hasOpacityPixel
|
|
28
|
+
}
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
|
|
31
|
-
function getLeafPaint(
|
|
32
|
+
function getLeafPaint(attrName: string, paint: IPaint, ui: IUI): ILeafPaint {
|
|
32
33
|
if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0) return undefined
|
|
33
34
|
const { boxBounds } = ui.__layout
|
|
34
35
|
|
|
@@ -37,14 +38,14 @@ function getLeafPaint(ui: IUI, paint: IPaint, attrName: string): ILeafPaint {
|
|
|
37
38
|
let { type, blendMode, color, opacity } = paint
|
|
38
39
|
return { type, blendMode, style: ColorConvert.string(color, opacity) }
|
|
39
40
|
case 'image':
|
|
40
|
-
return image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url])
|
|
41
|
+
return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url])
|
|
41
42
|
case 'linear':
|
|
42
|
-
return linearGradient(paint, boxBounds)
|
|
43
|
+
return PaintGradient.linearGradient(paint, boxBounds)
|
|
43
44
|
case 'radial':
|
|
44
|
-
return radialGradient(paint, boxBounds)
|
|
45
|
+
return PaintGradient.radialGradient(paint, boxBounds)
|
|
45
46
|
case 'angular':
|
|
46
|
-
return conicGradient(paint, boxBounds)
|
|
47
|
+
return PaintGradient.conicGradient(paint, boxBounds)
|
|
47
48
|
default:
|
|
48
|
-
return (paint as IRGB).r ? { type: 'solid', style: ColorConvert.string(paint) } : undefined
|
|
49
|
+
return (paint as IRGB).r !== undefined ? { type: 'solid', style: ColorConvert.string(paint) } : undefined
|
|
49
50
|
}
|
|
50
51
|
}
|
package/src/Fill.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { ILeaferCanvas } from '@leafer/interface'
|
|
2
2
|
|
|
3
3
|
import { ILeafPaint, IUI } from '@leafer-ui/interface'
|
|
4
|
+
import { PaintImage } from "@leafer-ui/draw"
|
|
4
5
|
|
|
5
|
-
import { checkImage } from './paint/image'
|
|
6
6
|
import { fillText } from './FillText'
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
export function fill(ui: IUI, canvas: ILeaferCanvas
|
|
9
|
+
export function fill(fill: string, ui: IUI, canvas: ILeaferCanvas): void {
|
|
10
10
|
canvas.fillStyle = fill
|
|
11
11
|
ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill())
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
export function fills(ui: IUI, canvas: ILeaferCanvas
|
|
15
|
+
export function fills(fills: ILeafPaint[], ui: IUI, canvas: ILeaferCanvas): void {
|
|
16
16
|
let item: ILeafPaint
|
|
17
17
|
const { windingRule, __font } = ui.__
|
|
18
18
|
for (let i = 0, len = fills.length; i < len; i++) {
|
|
19
19
|
item = fills[i]
|
|
20
20
|
|
|
21
|
-
if (item.image && checkImage(ui, canvas, item, !__font)) continue
|
|
21
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, !__font)) continue
|
|
22
22
|
|
|
23
23
|
if (item.style) {
|
|
24
24
|
|
package/src/Shape.ts
CHANGED
|
@@ -8,52 +8,52 @@ const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper
|
|
|
8
8
|
|
|
9
9
|
export function shape(ui: IUI, current: ILeaferCanvas, options: IRenderOptions): ICachedShape {
|
|
10
10
|
const canvas = current.getSameCanvas()
|
|
11
|
+
const nowWorld = ui.__nowWorld
|
|
11
12
|
|
|
12
|
-
let bounds: IBoundsData,
|
|
13
|
-
let worldCanvas: ILeaferCanvas
|
|
13
|
+
let bounds: IBoundsData, fitMatrix: IMatrix, shapeBounds: IBoundsData, worldCanvas: ILeaferCanvas
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
let { scaleX, scaleY } = __world
|
|
15
|
+
let { scaleX, scaleY } = nowWorld
|
|
17
16
|
if (scaleX < 0) scaleX = -scaleX
|
|
18
17
|
if (scaleY < 0) scaleY = -scaleY
|
|
19
18
|
|
|
20
|
-
if (
|
|
19
|
+
if (current.bounds.includes(nowWorld)) {
|
|
20
|
+
|
|
21
|
+
worldCanvas = canvas
|
|
22
|
+
bounds = shapeBounds = nowWorld
|
|
23
|
+
|
|
24
|
+
} else {
|
|
21
25
|
|
|
22
26
|
const { renderShapeSpread: spread } = ui.__layout
|
|
23
|
-
const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread *
|
|
24
|
-
|
|
27
|
+
const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, scaleX === scaleY ? spread * scaleX : [spread * scaleY, spread * scaleX]) : current.bounds, nowWorld)
|
|
28
|
+
fitMatrix = current.bounds.getFitMatrix(worldClipBounds)
|
|
29
|
+
let { a: fitScaleX, d: fitScaleY } = fitMatrix
|
|
25
30
|
|
|
26
|
-
if (
|
|
31
|
+
if (fitMatrix.a < 1) {
|
|
27
32
|
worldCanvas = current.getSameCanvas()
|
|
28
33
|
ui.__renderShape(worldCanvas, options)
|
|
29
34
|
|
|
30
|
-
scaleX *=
|
|
31
|
-
scaleY *=
|
|
35
|
+
scaleX *= fitScaleX
|
|
36
|
+
scaleY *= fitScaleY
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
shapeBounds = getOuterOf(
|
|
35
|
-
bounds = getByMove(shapeBounds, -
|
|
36
|
-
|
|
37
|
-
if (options.matrix) matrix.multiply(options.matrix)
|
|
38
|
-
options = { ...options, matrix }
|
|
39
|
-
|
|
40
|
-
} else {
|
|
39
|
+
shapeBounds = getOuterOf(nowWorld, fitMatrix)
|
|
40
|
+
bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f)
|
|
41
41
|
|
|
42
42
|
if (options.matrix) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
bounds = shapeBounds = __world
|
|
43
|
+
const { matrix } = options
|
|
44
|
+
fitMatrix.multiply(matrix)
|
|
45
|
+
fitScaleX *= matrix.scaleX
|
|
46
|
+
fitScaleY *= matrix.scaleY
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
options = { ...options, matrix: fitMatrix.withScale(fitScaleX, fitScaleY) }
|
|
50
|
+
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
ui.__renderShape(canvas, options)
|
|
54
54
|
|
|
55
55
|
return {
|
|
56
|
-
canvas, matrix, bounds,
|
|
56
|
+
canvas, matrix: fitMatrix, bounds,
|
|
57
57
|
worldCanvas, shapeBounds, scaleX, scaleY
|
|
58
58
|
}
|
|
59
59
|
}
|
package/src/Stroke.ts
CHANGED
|
@@ -5,14 +5,14 @@ import { IUI, ILeafPaint } from '@leafer-ui/interface'
|
|
|
5
5
|
import { strokeText, drawStrokesStyle } from './StrokeText'
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
export function stroke(ui: IUI, canvas: ILeaferCanvas
|
|
8
|
+
export function stroke(stroke: string, ui: IUI, canvas: ILeaferCanvas): void {
|
|
9
9
|
const options = ui.__
|
|
10
|
-
const {
|
|
11
|
-
if (!
|
|
10
|
+
const { __strokeWidth, strokeAlign, __font } = options
|
|
11
|
+
if (!__strokeWidth) return
|
|
12
12
|
|
|
13
13
|
if (__font) {
|
|
14
14
|
|
|
15
|
-
strokeText(ui, canvas
|
|
15
|
+
strokeText(stroke, ui, canvas)
|
|
16
16
|
|
|
17
17
|
} else {
|
|
18
18
|
|
|
@@ -20,14 +20,14 @@ export function stroke(ui: IUI, canvas: ILeaferCanvas, stroke: string): void {
|
|
|
20
20
|
|
|
21
21
|
case 'center':
|
|
22
22
|
|
|
23
|
-
canvas.setStroke(stroke,
|
|
23
|
+
canvas.setStroke(stroke, __strokeWidth, options)
|
|
24
24
|
canvas.stroke()
|
|
25
25
|
break
|
|
26
26
|
|
|
27
27
|
case 'inside':
|
|
28
28
|
|
|
29
29
|
canvas.save()
|
|
30
|
-
canvas.setStroke(stroke,
|
|
30
|
+
canvas.setStroke(stroke, __strokeWidth * 2, options)
|
|
31
31
|
|
|
32
32
|
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip()
|
|
33
33
|
canvas.stroke()
|
|
@@ -37,8 +37,8 @@ export function stroke(ui: IUI, canvas: ILeaferCanvas, stroke: string): void {
|
|
|
37
37
|
break
|
|
38
38
|
|
|
39
39
|
case 'outside':
|
|
40
|
-
const out = canvas.getSameCanvas(true)
|
|
41
|
-
out.setStroke(stroke,
|
|
40
|
+
const out = canvas.getSameCanvas(true, true)
|
|
41
|
+
out.setStroke(stroke, __strokeWidth * 2, options)
|
|
42
42
|
|
|
43
43
|
ui.__drawRenderPath(out)
|
|
44
44
|
|
|
@@ -47,9 +47,13 @@ export function stroke(ui: IUI, canvas: ILeaferCanvas, stroke: string): void {
|
|
|
47
47
|
options.windingRule ? out.clip(options.windingRule) : out.clip()
|
|
48
48
|
out.clearWorld(ui.__layout.renderBounds)
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
if (ui.__worldFlipped) {
|
|
51
|
+
canvas.copyWorldByReset(out, ui.__nowWorld)
|
|
52
|
+
} else {
|
|
53
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds)
|
|
54
|
+
}
|
|
52
55
|
|
|
56
|
+
out.recycle(ui.__nowWorld)
|
|
53
57
|
break
|
|
54
58
|
}
|
|
55
59
|
|
|
@@ -57,48 +61,53 @@ export function stroke(ui: IUI, canvas: ILeaferCanvas, stroke: string): void {
|
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
|
|
60
|
-
export function strokes(ui: IUI, canvas: ILeaferCanvas
|
|
64
|
+
export function strokes(strokes: ILeafPaint[], ui: IUI, canvas: ILeaferCanvas): void {
|
|
61
65
|
const options = ui.__
|
|
62
|
-
const {
|
|
63
|
-
if (!
|
|
66
|
+
const { __strokeWidth, strokeAlign, __font } = options
|
|
67
|
+
if (!__strokeWidth) return
|
|
64
68
|
|
|
65
69
|
if (__font) {
|
|
66
70
|
|
|
67
|
-
strokeText(ui, canvas
|
|
71
|
+
strokeText(strokes, ui, canvas)
|
|
68
72
|
|
|
69
73
|
} else {
|
|
70
74
|
|
|
71
75
|
switch (strokeAlign) {
|
|
72
76
|
|
|
73
77
|
case 'center':
|
|
74
|
-
canvas.setStroke(undefined,
|
|
75
|
-
drawStrokesStyle(
|
|
78
|
+
canvas.setStroke(undefined, __strokeWidth, options)
|
|
79
|
+
drawStrokesStyle(strokes, false, ui, canvas)
|
|
76
80
|
break
|
|
77
81
|
|
|
78
82
|
case 'inside':
|
|
79
83
|
canvas.save()
|
|
80
|
-
canvas.setStroke(undefined,
|
|
84
|
+
canvas.setStroke(undefined, __strokeWidth * 2, options)
|
|
81
85
|
options.windingRule ? canvas.clip(options.windingRule) : canvas.clip()
|
|
82
86
|
|
|
83
|
-
drawStrokesStyle(
|
|
87
|
+
drawStrokesStyle(strokes, false, ui, canvas)
|
|
84
88
|
|
|
85
89
|
canvas.restore()
|
|
86
90
|
break
|
|
87
91
|
|
|
88
92
|
case 'outside':
|
|
89
93
|
const { renderBounds } = ui.__layout
|
|
90
|
-
const out = canvas.getSameCanvas(true)
|
|
94
|
+
const out = canvas.getSameCanvas(true, true)
|
|
91
95
|
ui.__drawRenderPath(out)
|
|
92
96
|
|
|
93
|
-
out.setStroke(undefined,
|
|
97
|
+
out.setStroke(undefined, __strokeWidth * 2, options)
|
|
94
98
|
|
|
95
|
-
drawStrokesStyle(
|
|
99
|
+
drawStrokesStyle(strokes, false, ui, out)
|
|
96
100
|
|
|
97
101
|
options.windingRule ? out.clip(options.windingRule) : out.clip()
|
|
98
102
|
out.clearWorld(renderBounds)
|
|
99
103
|
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
if (ui.__worldFlipped) {
|
|
105
|
+
canvas.copyWorldByReset(out, ui.__nowWorld)
|
|
106
|
+
} else {
|
|
107
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, renderBounds)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
out.recycle(ui.__nowWorld)
|
|
102
111
|
break
|
|
103
112
|
}
|
|
104
113
|
|
package/src/StrokeText.ts
CHANGED
|
@@ -1,43 +1,48 @@
|
|
|
1
1
|
import { ILeaferCanvas } from '@leafer/interface'
|
|
2
2
|
|
|
3
3
|
import { IUI, ITextRowData, ILeafPaint, IStrokeAlign, ILeafStrokePaint } from '@leafer-ui/interface'
|
|
4
|
+
import { PaintImage } from "@leafer-ui/draw"
|
|
4
5
|
|
|
5
6
|
import { fillText } from './FillText'
|
|
6
|
-
import { checkImage } from './paint/image'
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
export function strokeText(ui: IUI, canvas: ILeaferCanvas
|
|
9
|
+
export function strokeText(stroke: string | ILeafPaint[], ui: IUI, canvas: ILeaferCanvas): void {
|
|
10
10
|
const { strokeAlign } = ui.__
|
|
11
11
|
const isStrokes = typeof stroke !== 'string'
|
|
12
12
|
switch (strokeAlign) {
|
|
13
13
|
case 'center':
|
|
14
14
|
canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__)
|
|
15
|
-
isStrokes ? drawStrokesStyle(
|
|
15
|
+
isStrokes ? drawStrokesStyle(stroke as ILeafPaint[], true, ui, canvas) : drawTextStroke(ui, canvas)
|
|
16
16
|
break
|
|
17
17
|
case 'inside':
|
|
18
|
-
drawAlignStroke(
|
|
18
|
+
drawAlignStroke('inside', stroke, isStrokes, ui, canvas)
|
|
19
19
|
break
|
|
20
20
|
case 'outside':
|
|
21
|
-
drawAlignStroke(
|
|
21
|
+
drawAlignStroke('outside', stroke, isStrokes, ui, canvas)
|
|
22
22
|
break
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function drawAlignStroke(
|
|
27
|
-
const {
|
|
26
|
+
function drawAlignStroke(align: IStrokeAlign, stroke: string | ILeafPaint[], isStrokes: boolean, ui: IUI, canvas: ILeaferCanvas): void {
|
|
27
|
+
const { __strokeWidth, __font } = ui.__
|
|
28
28
|
|
|
29
|
-
const out = canvas.getSameCanvas(true)
|
|
30
|
-
out.setStroke(isStrokes ? undefined : stroke,
|
|
29
|
+
const out = canvas.getSameCanvas(true, true)
|
|
30
|
+
out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__)
|
|
31
31
|
|
|
32
32
|
out.font = __font
|
|
33
|
-
isStrokes ? drawStrokesStyle(
|
|
33
|
+
isStrokes ? drawStrokesStyle(stroke as ILeafPaint[], true, ui, out) : drawTextStroke(ui, out)
|
|
34
34
|
|
|
35
35
|
out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in'
|
|
36
36
|
fillText(ui, out)
|
|
37
37
|
out.blendMode = 'normal'
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
if (ui.__worldFlipped) {
|
|
40
|
+
canvas.copyWorldByReset(out, ui.__nowWorld)
|
|
41
|
+
} else {
|
|
42
|
+
canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
out.recycle(ui.__nowWorld)
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
export function drawTextStroke(ui: IUI, canvas: ILeaferCanvas): void {
|
|
@@ -61,12 +66,12 @@ export function drawTextStroke(ui: IUI, canvas: ILeaferCanvas): void {
|
|
|
61
66
|
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
export function drawStrokesStyle(
|
|
69
|
+
export function drawStrokesStyle(strokes: ILeafStrokePaint[], isText: boolean, ui: IUI, canvas: ILeaferCanvas): void {
|
|
65
70
|
let item: ILeafStrokePaint
|
|
66
71
|
for (let i = 0, len = strokes.length; i < len; i++) {
|
|
67
72
|
item = strokes[i]
|
|
68
73
|
|
|
69
|
-
if (item.image && checkImage(ui, canvas, item, false)) continue
|
|
74
|
+
if (item.image && PaintImage.checkImage(ui, canvas, item, false)) continue
|
|
70
75
|
|
|
71
76
|
if (item.style) {
|
|
72
77
|
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { IPaintModule } from '@leafer-ui/interface'
|
|
2
|
+
|
|
3
|
+
import { fill, fills } from './Fill'
|
|
4
|
+
import { fillText } from './FillText'
|
|
5
|
+
import { stroke, strokes } from './Stroke'
|
|
6
|
+
import { strokeText, drawTextStroke } from './StrokeText'
|
|
7
|
+
import { shape } from './Shape'
|
|
8
|
+
import { compute } from './Compute'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export const PaintModule: IPaintModule = {
|
|
12
|
+
compute,
|
|
13
|
+
fill,
|
|
14
|
+
fills,
|
|
15
|
+
fillText,
|
|
16
|
+
stroke,
|
|
17
|
+
strokes,
|
|
18
|
+
strokeText,
|
|
19
|
+
drawTextStroke,
|
|
20
|
+
shape
|
|
21
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { IUI, ILeafPaint, ICachedShape, IUIData } from '@leafer-ui/interface';
|
|
1
|
+
import { IPaintModule } from '@leafer-ui/interface';
|
|
3
2
|
|
|
4
|
-
declare
|
|
5
|
-
declare function fills(ui: IUI, canvas: ILeaferCanvas, fills: ILeafPaint[]): void;
|
|
3
|
+
declare const PaintModule: IPaintModule;
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
declare function stroke(ui: IUI, canvas: ILeaferCanvas, stroke: string): void;
|
|
10
|
-
declare function strokes(ui: IUI, canvas: ILeaferCanvas, strokes: ILeafPaint[]): void;
|
|
11
|
-
|
|
12
|
-
declare function strokeText(ui: IUI, canvas: ILeaferCanvas, stroke: string | ILeafPaint[]): void;
|
|
13
|
-
declare function drawTextStroke(ui: IUI, canvas: ILeaferCanvas): void;
|
|
14
|
-
|
|
15
|
-
declare function shape(ui: IUI, current: ILeaferCanvas, options: IRenderOptions): ICachedShape;
|
|
16
|
-
|
|
17
|
-
declare function compute(ui: IUI, attrName: string): void;
|
|
18
|
-
|
|
19
|
-
declare function recycleImage(data: IUIData, attrName: string): IBooleanMap;
|
|
20
|
-
|
|
21
|
-
export { compute, drawTextStroke, fill, fillText, fills, recycleImage, shape, stroke, strokeText, strokes };
|
|
5
|
+
export { PaintModule };
|
package/src/paint/conic.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { IMatrixData, IPointData, IBoundsData } from '@leafer/interface'
|
|
2
|
-
import { Platform, PointHelper, MatrixHelper } from '@leafer/core'
|
|
3
|
-
|
|
4
|
-
import { IGradientPaint, ILeafPaint } from '@leafer-ui/interface'
|
|
5
|
-
|
|
6
|
-
import { applyStops } from './linear'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const { set, getAngle, getDistance } = PointHelper
|
|
10
|
-
const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper
|
|
11
|
-
|
|
12
|
-
const defaultFrom = { x: 0.5, y: 0.5 }
|
|
13
|
-
const defaultTo = { x: 0.5, y: 1 }
|
|
14
|
-
|
|
15
|
-
const realFrom = {} as IPointData
|
|
16
|
-
const realTo = {} as IPointData
|
|
17
|
-
|
|
18
|
-
export function conicGradient(paint: IGradientPaint, box: IBoundsData): ILeafPaint {
|
|
19
|
-
|
|
20
|
-
let { from, to, type, opacity, blendMode, stretch } = paint
|
|
21
|
-
|
|
22
|
-
from || (from = defaultFrom)
|
|
23
|
-
to || (to = defaultTo)
|
|
24
|
-
|
|
25
|
-
const { x, y, width, height } = box
|
|
26
|
-
|
|
27
|
-
set(realFrom, x + from.x * width, y + from.y * height)
|
|
28
|
-
set(realTo, x + to.x * width, y + to.y * height)
|
|
29
|
-
|
|
30
|
-
const transform: IMatrixData = get()
|
|
31
|
-
const angle = getAngle(realFrom, realTo)
|
|
32
|
-
|
|
33
|
-
if (Platform.conicGradientRotate90) {
|
|
34
|
-
scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1)
|
|
35
|
-
rotateOfOuter(transform, realFrom, angle + 90)
|
|
36
|
-
} else {
|
|
37
|
-
scaleOfOuter(transform, realFrom, 1, width / height * (stretch || 1))
|
|
38
|
-
rotateOfOuter(transform, realFrom, angle)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const style = Platform.conicGradientSupport ? Platform.canvas.createConicGradient(0, realFrom.x, realFrom.y) : Platform.canvas.createRadialGradient(realFrom.x, realFrom.y, 0, realFrom.x, realFrom.y, getDistance(realFrom, realTo))
|
|
42
|
-
applyStops(style, paint.stops, opacity)
|
|
43
|
-
|
|
44
|
-
const data: ILeafPaint = { type, style, transform }
|
|
45
|
-
if (blendMode) data.blendMode = blendMode
|
|
46
|
-
return data
|
|
47
|
-
|
|
48
|
-
}
|
package/src/paint/image/check.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { ILeaferCanvas } from '@leafer/interface'
|
|
3
|
-
import { ImageManager } from '@leafer/core'
|
|
4
|
-
|
|
5
|
-
import { IUI, ILeafPaint } from '@leafer-ui/interface'
|
|
6
|
-
|
|
7
|
-
import { createPattern } from './pattern'
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export function checkImage(ui: IUI, canvas: ILeaferCanvas, paint: ILeafPaint, allowPaint?: boolean): boolean {
|
|
11
|
-
const { scaleX, scaleY } = ui.__world
|
|
12
|
-
|
|
13
|
-
if (!paint.data || paint.patternId === scaleX + '-' + scaleY) {
|
|
14
|
-
return false
|
|
15
|
-
} else {
|
|
16
|
-
|
|
17
|
-
if (allowPaint) {
|
|
18
|
-
if (paint.image.isSVG && paint.data.mode !== 'repeat') {
|
|
19
|
-
let { width, height } = paint.data
|
|
20
|
-
width *= scaleX * canvas.pixelRatio
|
|
21
|
-
height *= scaleY * canvas.pixelRatio
|
|
22
|
-
allowPaint = width > 4096 || height > 4096
|
|
23
|
-
} else {
|
|
24
|
-
allowPaint = false
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (allowPaint) {
|
|
29
|
-
canvas.save()
|
|
30
|
-
canvas.clip()
|
|
31
|
-
const { data } = paint
|
|
32
|
-
if (paint.blendMode) canvas.blendMode = paint.blendMode
|
|
33
|
-
if (data.opacity) canvas.opacity *= data.opacity
|
|
34
|
-
if (data.transform) canvas.transform(data.transform)
|
|
35
|
-
canvas.drawImage(paint.image.view as any, 0, 0, data.width, data.height)
|
|
36
|
-
canvas.restore()
|
|
37
|
-
return true
|
|
38
|
-
} else {
|
|
39
|
-
if (!paint.style) {
|
|
40
|
-
createPattern(ui, paint, canvas.pixelRatio)
|
|
41
|
-
} else {
|
|
42
|
-
ImageManager.patternTasker.add(async () => {
|
|
43
|
-
if (canvas.bounds.hit(ui.__world) && createPattern(ui, paint, canvas.pixelRatio)) ui.forceUpdate('surface')
|
|
44
|
-
}, 300)
|
|
45
|
-
}
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
package/src/paint/image/data.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { IBoundsData, ILeaferImage } from '@leafer/interface'
|
|
2
|
-
import { MatrixHelper } from '@leafer/core'
|
|
3
|
-
|
|
4
|
-
import { IImagePaint, ILeafPaint, ILeafPaintPatternData } from '@leafer-ui/interface'
|
|
5
|
-
|
|
6
|
-
import { clipMode, fillOrFitMode, repeatMode } from './mode'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const { get, translate } = MatrixHelper
|
|
10
|
-
|
|
11
|
-
export function createData(leafPaint: ILeafPaint, image: ILeaferImage, paint: IImagePaint, box: IBoundsData): void {
|
|
12
|
-
let { width, height } = image
|
|
13
|
-
|
|
14
|
-
const { opacity, mode, offset, scale, rotation, blendMode } = paint
|
|
15
|
-
const sameBox = box.width === width && box.height === height
|
|
16
|
-
if (blendMode) leafPaint.blendMode = blendMode
|
|
17
|
-
|
|
18
|
-
const data: ILeafPaintPatternData = leafPaint.data = { mode }
|
|
19
|
-
|
|
20
|
-
switch (mode) {
|
|
21
|
-
case 'strench':
|
|
22
|
-
if (!sameBox) width = box.width, height = box.height
|
|
23
|
-
if (box.x || box.y) {
|
|
24
|
-
data.transform = get()
|
|
25
|
-
translate(data.transform, box.x, box.y)
|
|
26
|
-
}
|
|
27
|
-
break
|
|
28
|
-
case 'clip':
|
|
29
|
-
if (offset || scale || rotation) clipMode(data, box, offset, scale, rotation)
|
|
30
|
-
break
|
|
31
|
-
case 'repeat':
|
|
32
|
-
if (!sameBox || scale || rotation) repeatMode(data, box, width, height, scale as number, rotation)
|
|
33
|
-
break
|
|
34
|
-
case 'fit':
|
|
35
|
-
case 'cover':
|
|
36
|
-
default:
|
|
37
|
-
if (!sameBox || rotation) fillOrFitMode(data, mode, box, width, height, rotation)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
data.width = width
|
|
41
|
-
data.height = height
|
|
42
|
-
if (opacity) data.opacity = opacity
|
|
43
|
-
}
|
package/src/paint/image/image.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { IBoundsData, IImageEvent, ISizeData } from '@leafer/interface'
|
|
2
|
-
import { ImageEvent, ImageManager } from '@leafer/core'
|
|
3
|
-
|
|
4
|
-
import { IUI, IImagePaint, ILeafPaint } from '@leafer-ui/interface'
|
|
5
|
-
|
|
6
|
-
import { createData } from './data'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export function image(ui: IUI, attrName: string, attrValue: IImagePaint, box: IBoundsData, firstUse: boolean): ILeafPaint {
|
|
10
|
-
const leafPaint: ILeafPaint = { type: attrValue.type }
|
|
11
|
-
const image = leafPaint.image = ImageManager.get(attrValue)
|
|
12
|
-
|
|
13
|
-
const event: IImageEvent = (firstUse || image.loading) && { target: ui, image, attrName, attrValue }
|
|
14
|
-
|
|
15
|
-
if (image.ready) {
|
|
16
|
-
|
|
17
|
-
if (hasNaturalSize(ui, attrName, image)) createData(leafPaint, image, attrValue, box)
|
|
18
|
-
|
|
19
|
-
if (firstUse) {
|
|
20
|
-
emit(ImageEvent.LOAD, event)
|
|
21
|
-
emit(ImageEvent.LOADED, event)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
} else if (image.error) {
|
|
25
|
-
|
|
26
|
-
if (firstUse) {
|
|
27
|
-
ui.forceUpdate('surface')
|
|
28
|
-
event.error = image.error
|
|
29
|
-
emit(ImageEvent.ERROR, event)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
} else {
|
|
33
|
-
|
|
34
|
-
if (firstUse) emit(ImageEvent.LOAD, event)
|
|
35
|
-
|
|
36
|
-
leafPaint.loadId = image.load(
|
|
37
|
-
() => {
|
|
38
|
-
if (!ui.destroyed) {
|
|
39
|
-
|
|
40
|
-
if (hasNaturalSize(ui, attrName, image)) {
|
|
41
|
-
createData(leafPaint, image, attrValue, box)
|
|
42
|
-
ui.forceUpdate('surface')
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
emit(ImageEvent.LOADED, event)
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
(error) => {
|
|
49
|
-
ui.forceUpdate('surface')
|
|
50
|
-
event.error = error
|
|
51
|
-
emit(ImageEvent.ERROR, event)
|
|
52
|
-
}
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return leafPaint
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
function hasNaturalSize(ui: IUI, attrName: string, image: ISizeData): boolean {
|
|
62
|
-
if (attrName === 'fill' && !ui.__.__naturalWidth) {
|
|
63
|
-
const { __: d } = ui
|
|
64
|
-
d.__naturalWidth = image.width
|
|
65
|
-
d.__naturalHeight = image.height
|
|
66
|
-
if (!d.__getInput('width') || !d.__getInput('height')) {
|
|
67
|
-
ui.forceUpdate('width')
|
|
68
|
-
return false
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return true
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function emit(type: string, data: IImageEvent): void {
|
|
75
|
-
if (data.target.hasEvent(type)) data.target.emitEvent(new ImageEvent(type, data))
|
|
76
|
-
}
|
|
77
|
-
|
package/src/paint/image/index.ts
DELETED
package/src/paint/image/mode.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { IBoundsData } from '@leafer/interface'
|
|
2
|
-
import { MatrixHelper } from '@leafer/core'
|
|
3
|
-
|
|
4
|
-
import { IMatrixData, IImagePaintMode, IPointData, ILeafPaintPatternData } from '@leafer-ui/interface'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const { get, rotateOfOuter, translate, scaleOfOuter, scale: scaleHelper, rotate } = MatrixHelper
|
|
8
|
-
|
|
9
|
-
export function fillOrFitMode(data: ILeafPaintPatternData, mode: IImagePaintMode, box: IBoundsData, width: number, height: number, rotation: number): void {
|
|
10
|
-
const transform: IMatrixData = get()
|
|
11
|
-
const swap = rotation && rotation !== 180
|
|
12
|
-
const sw = box.width / (swap ? height : width)
|
|
13
|
-
const sh = box.height / (swap ? width : height)
|
|
14
|
-
const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh)
|
|
15
|
-
const x = box.x + (box.width - width * scale) / 2
|
|
16
|
-
const y = box.y + (box.height - height * scale) / 2
|
|
17
|
-
translate(transform, x, y)
|
|
18
|
-
scaleHelper(transform, scale)
|
|
19
|
-
if (rotation) rotateOfOuter(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation)
|
|
20
|
-
data.scaleX = data.scaleY = scale
|
|
21
|
-
data.transform = transform
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export function clipMode(data: ILeafPaintPatternData, box: IBoundsData, offset: IPointData, scale: number | IPointData, rotation: number): void {
|
|
26
|
-
const transform: IMatrixData = get()
|
|
27
|
-
translate(transform, box.x, box.y)
|
|
28
|
-
if (offset) translate(transform, offset.x, offset.y)
|
|
29
|
-
if (scale) {
|
|
30
|
-
typeof scale === 'number' ? scaleHelper(transform, scale) : scaleHelper(transform, scale.x, scale.y)
|
|
31
|
-
data.scaleX = transform.a
|
|
32
|
-
data.scaleY = transform.d
|
|
33
|
-
}
|
|
34
|
-
if (rotation) rotate(transform, rotation)
|
|
35
|
-
data.transform = transform
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export function repeatMode(data: ILeafPaintPatternData, box: IBoundsData, width: number, height: number, scale: number, rotation: number): void {
|
|
40
|
-
const transform = get()
|
|
41
|
-
|
|
42
|
-
if (rotation) {
|
|
43
|
-
rotate(transform, rotation)
|
|
44
|
-
switch (rotation) {
|
|
45
|
-
case 90:
|
|
46
|
-
translate(transform, height, 0)
|
|
47
|
-
break
|
|
48
|
-
case 180:
|
|
49
|
-
translate(transform, width, height)
|
|
50
|
-
break
|
|
51
|
-
case 270:
|
|
52
|
-
translate(transform, 0, width)
|
|
53
|
-
break
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
translate(transform, box.x, box.y)
|
|
57
|
-
if (scale) {
|
|
58
|
-
scaleOfOuter(transform, box, scale)
|
|
59
|
-
data.scaleX = data.scaleY = scale
|
|
60
|
-
}
|
|
61
|
-
data.transform = transform
|
|
62
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { Platform, MatrixHelper } from '@leafer/core'
|
|
2
|
-
|
|
3
|
-
import { IUI, ILeafPaint, IMatrixData } from '@leafer-ui/interface'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const { get, scale: scaleHelper, copy } = MatrixHelper
|
|
7
|
-
|
|
8
|
-
export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): boolean {
|
|
9
|
-
|
|
10
|
-
let { scaleX, scaleY } = ui.__world
|
|
11
|
-
|
|
12
|
-
const id = scaleX + '-' + scaleY
|
|
13
|
-
|
|
14
|
-
if (paint.patternId !== id && !ui.destroyed) {
|
|
15
|
-
|
|
16
|
-
paint.patternId = id
|
|
17
|
-
|
|
18
|
-
scaleX = Math.abs(scaleX) // maybe -1
|
|
19
|
-
scaleY = Math.abs(scaleY)
|
|
20
|
-
|
|
21
|
-
const { image, data } = paint
|
|
22
|
-
const maxWidth = image.isSVG ? 4096 : Math.min(image.width, 4096)
|
|
23
|
-
const maxHeight = image.isSVG ? 4096 : Math.min(image.height, 4096)
|
|
24
|
-
let scale: number, matrix: IMatrixData, { width, height, scaleX: sx, scaleY: sy, opacity, transform, mode } = data
|
|
25
|
-
|
|
26
|
-
if (sx) {
|
|
27
|
-
matrix = get()
|
|
28
|
-
copy(matrix, transform)
|
|
29
|
-
scaleHelper(matrix, 1 / sx, 1 / sy)
|
|
30
|
-
scaleX *= sx
|
|
31
|
-
scaleY *= sy
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
scaleX *= pixelRatio
|
|
35
|
-
scaleY *= pixelRatio
|
|
36
|
-
width *= scaleX
|
|
37
|
-
height *= scaleY
|
|
38
|
-
|
|
39
|
-
if (width > maxWidth || height > maxHeight) {
|
|
40
|
-
scale = Math.max(width / maxWidth, height / maxHeight)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (scale) {
|
|
44
|
-
scaleX /= scale
|
|
45
|
-
scaleY /= scale
|
|
46
|
-
width /= scale
|
|
47
|
-
height /= scale
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (sx) {
|
|
51
|
-
scaleX /= sx
|
|
52
|
-
scaleY /= sy
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (transform || scaleX !== 1 || scaleY !== 1) {
|
|
56
|
-
if (!matrix) {
|
|
57
|
-
matrix = get()
|
|
58
|
-
if (transform) copy(matrix, transform)
|
|
59
|
-
}
|
|
60
|
-
scaleHelper(matrix, 1 / scaleX, 1 / scaleY)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const style = Platform.canvas.createPattern(image.getCanvas(width < 1 ? 1 : width, height < 1 ? 1 : height, opacity) as any, mode === 'repeat' ? 'repeat' : (Platform.origin.noRepeat || 'no-repeat'))
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
if (paint.transform) paint.transform = null
|
|
67
|
-
if (matrix) style.setTransform ? style.setTransform(matrix) : paint.transform = matrix
|
|
68
|
-
} catch {
|
|
69
|
-
paint.transform = matrix
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
paint.style = style
|
|
73
|
-
|
|
74
|
-
return true
|
|
75
|
-
|
|
76
|
-
} else {
|
|
77
|
-
|
|
78
|
-
return false
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { IBooleanMap, ILeaferImage } from '@leafer/interface'
|
|
2
|
-
import { ImageManager } from '@leafer/core'
|
|
3
|
-
|
|
4
|
-
import { IImagePaint, ILeafPaint, IUIData } from '@leafer-ui/interface'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export function recycleImage(data: IUIData, attrName: string): IBooleanMap {
|
|
8
|
-
const paints = (attrName === 'fill' ? data._fill : data._stroke) as ILeafPaint[]
|
|
9
|
-
|
|
10
|
-
if (paints instanceof Array) {
|
|
11
|
-
|
|
12
|
-
let image: ILeaferImage, recycleMap: IBooleanMap, input: IImagePaint[], url: string
|
|
13
|
-
|
|
14
|
-
for (let i = 0, len = paints.length; i < len; i++) {
|
|
15
|
-
|
|
16
|
-
image = paints[i].image
|
|
17
|
-
url = image && image.url
|
|
18
|
-
|
|
19
|
-
if (url) {
|
|
20
|
-
if (!recycleMap) recycleMap = {}
|
|
21
|
-
recycleMap[url] = true
|
|
22
|
-
ImageManager.recycle(image)
|
|
23
|
-
|
|
24
|
-
// stop load
|
|
25
|
-
if (image.loading) {
|
|
26
|
-
if (!input) {
|
|
27
|
-
input = (data.__input && data.__input[attrName]) || []
|
|
28
|
-
if (!(input instanceof Array)) input = [input]
|
|
29
|
-
}
|
|
30
|
-
image.unload(paints[i].loadId, !input.some((item: IImagePaint) => item.url === url))
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return recycleMap
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return null
|
|
41
|
-
}
|
package/src/paint/linear.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { IObject, IBoundsData } from '@leafer/interface'
|
|
2
|
-
import { Platform } from '@leafer/core'
|
|
3
|
-
|
|
4
|
-
import { IGradientPaint, ILeafPaint, IColorStop } from '@leafer-ui/interface'
|
|
5
|
-
import { ColorConvert } from '@leafer-ui/core'
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const defaultFrom = { x: 0.5, y: 0 }
|
|
9
|
-
const defaultTo = { x: 0.5, y: 1 }
|
|
10
|
-
|
|
11
|
-
export function linearGradient(paint: IGradientPaint, box: IBoundsData): ILeafPaint {
|
|
12
|
-
|
|
13
|
-
let { from, to, type, blendMode, opacity } = paint
|
|
14
|
-
|
|
15
|
-
from || (from = defaultFrom)
|
|
16
|
-
to || (to = defaultTo)
|
|
17
|
-
|
|
18
|
-
const style = Platform.canvas.createLinearGradient(box.x + from.x * box.width, box.y + from.y * box.height, box.x + to.x * box.width, box.y + to.y * box.height)
|
|
19
|
-
applyStops(style, paint.stops, opacity)
|
|
20
|
-
|
|
21
|
-
const data: ILeafPaint = { type, style }
|
|
22
|
-
if (blendMode) data.blendMode = blendMode
|
|
23
|
-
return data
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function applyStops(gradient: IObject, stops: IColorStop[], opacity: number): void {
|
|
28
|
-
let stop: IColorStop
|
|
29
|
-
for (let i = 0, len = stops.length; i < len; i++) {
|
|
30
|
-
stop = stops[i]
|
|
31
|
-
gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity))
|
|
32
|
-
}
|
|
33
|
-
}
|
package/src/paint/radial.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { IBoundsData } from '@leafer/interface'
|
|
2
|
-
import { Platform, PointHelper, MatrixHelper } from '@leafer/core'
|
|
3
|
-
|
|
4
|
-
import { IGradientPaint, ILeafPaint, IMatrixData, IPointData } from '@leafer-ui/interface'
|
|
5
|
-
|
|
6
|
-
import { applyStops } from './linear'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const { set, getAngle, getDistance } = PointHelper
|
|
10
|
-
const { get, rotateOfOuter, scaleOfOuter } = MatrixHelper
|
|
11
|
-
|
|
12
|
-
const defaultFrom = { x: 0.5, y: 0.5 }
|
|
13
|
-
const defaultTo = { x: 0.5, y: 1 }
|
|
14
|
-
|
|
15
|
-
const realFrom = {} as IPointData
|
|
16
|
-
const realTo = {} as IPointData
|
|
17
|
-
|
|
18
|
-
export function radialGradient(paint: IGradientPaint, box: IBoundsData): ILeafPaint {
|
|
19
|
-
|
|
20
|
-
let { from, to, type, opacity, blendMode, stretch } = paint
|
|
21
|
-
|
|
22
|
-
from || (from = defaultFrom)
|
|
23
|
-
to || (to = defaultTo)
|
|
24
|
-
|
|
25
|
-
const { x, y, width, height } = box
|
|
26
|
-
set(realFrom, x + from.x * width, y + from.y * height)
|
|
27
|
-
set(realTo, x + to.x * width, y + to.y * height)
|
|
28
|
-
|
|
29
|
-
let transform: IMatrixData
|
|
30
|
-
|
|
31
|
-
if (width !== height || stretch) {
|
|
32
|
-
transform = get()
|
|
33
|
-
scaleOfOuter(transform, realFrom, width / height * (stretch || 1), 1)
|
|
34
|
-
rotateOfOuter(transform, realFrom, getAngle(realFrom, realTo) + 90)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const style = Platform.canvas.createRadialGradient(realFrom.x, realFrom.y, 0, realFrom.x, realFrom.y, getDistance(realFrom, realTo))
|
|
38
|
-
applyStops(style, paint.stops, opacity)
|
|
39
|
-
|
|
40
|
-
const data: ILeafPaint = { type, style, transform }
|
|
41
|
-
if (blendMode) data.blendMode = blendMode
|
|
42
|
-
return data
|
|
43
|
-
|
|
44
|
-
}
|