@leafer-ui/paint 1.0.0-alpha.23 → 1.0.0-alpha.31
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 +3 -3
- package/src/Compute.ts +22 -19
- package/src/Fill.ts +11 -6
- package/src/FillText.ts +25 -0
- package/src/Shape.ts +5 -4
- package/src/Stroke.ts +70 -51
- package/src/StrokeText.ts +118 -0
- package/src/index.ts +3 -2
- package/src/paint/conic.ts +9 -6
- package/src/paint/image.ts +33 -29
- package/src/paint/linear.ts +5 -5
- package/src/paint/radial.ts +9 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer-ui/paint",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.31",
|
|
4
4
|
"description": "@leafer-ui/paint",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"leaferjs"
|
|
20
20
|
],
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@leafer/interface": "1.0.0-alpha.
|
|
23
|
-
"@leafer-ui/interface": "1.0.0-alpha.
|
|
22
|
+
"@leafer/interface": "1.0.0-alpha.31",
|
|
23
|
+
"@leafer-ui/interface": "1.0.0-alpha.31"
|
|
24
24
|
}
|
|
25
25
|
}
|
package/src/Compute.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IUI, IPaint, ILeafPaint } from '@leafer-ui/interface'
|
|
2
|
-
import {
|
|
1
|
+
import { IUI, IPaint, ILeafPaint, IRGB } from '@leafer-ui/interface'
|
|
2
|
+
import { ColorConvert } from '@leafer-ui/color'
|
|
3
3
|
|
|
4
4
|
import { image } from "./paint/image"
|
|
5
5
|
import { linearGradient } from './paint/linear'
|
|
@@ -16,33 +16,36 @@ export function computeStroke(ui: IUI): void {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function compute(ui: IUI, attrName: string): void {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
let paints = ui.__.__input[attrName] as IPaint[]
|
|
20
|
+
|
|
21
|
+
let item: ILeafPaint
|
|
22
|
+
const value: ILeafPaint[] = []
|
|
23
|
+
if (!(paints instanceof Array)) paints = [paints]
|
|
24
|
+
|
|
25
|
+
for (let i = 0, len = paints.length; i < len; i++) {
|
|
26
|
+
item = getLeafPaint(ui, paints[i], attrName)
|
|
27
|
+
if (item) value.push(item)
|
|
28
28
|
}
|
|
29
|
+
ui.__['_' + attrName] = value.length ? value : undefined
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
function getLeafPaint(ui: IUI, paint: IPaint, attrName: string): ILeafPaint {
|
|
32
|
-
if (paint.visible === false || paint.opacity === 0) return undefined
|
|
33
|
+
if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0) return undefined
|
|
34
|
+
const { boxBounds } = ui.__layout
|
|
33
35
|
|
|
34
|
-
const { width, height } = ui.__layout.boxBounds
|
|
35
36
|
switch (paint.type) {
|
|
36
37
|
case 'solid':
|
|
37
|
-
let { type, blendMode, color } = paint
|
|
38
|
-
return { type, blendMode, style:
|
|
38
|
+
let { type, blendMode, color, opacity } = paint
|
|
39
|
+
return { type, blendMode, style: ColorConvert.string(color, opacity) }
|
|
39
40
|
case 'image':
|
|
40
|
-
return image(ui, attrName, paint,
|
|
41
|
+
return image(ui, attrName, paint, boxBounds)
|
|
41
42
|
case 'linear':
|
|
42
|
-
return linearGradient(paint,
|
|
43
|
+
return linearGradient(paint, boxBounds)
|
|
43
44
|
case 'radial':
|
|
44
|
-
return radialGradient(paint,
|
|
45
|
+
return radialGradient(paint, boxBounds)
|
|
45
46
|
case 'angular':
|
|
46
|
-
return conicGradient(paint,
|
|
47
|
+
return conicGradient(paint, boxBounds)
|
|
48
|
+
default:
|
|
49
|
+
return (paint as IRGB).r ? { type: 'solid', style: ColorConvert.string(paint) } : undefined
|
|
47
50
|
}
|
|
48
51
|
}
|
package/src/Fill.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ILeaferCanvas } from '@leafer/interface'
|
|
2
2
|
|
|
3
3
|
import { ILeafPaint, IUI } from '@leafer-ui/interface'
|
|
4
|
+
import { drawText } from './FillText'
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
export function fill(ui: IUI, canvas: ILeaferCanvas, fill: string | object): void {
|
|
7
8
|
canvas.fillStyle = fill
|
|
8
|
-
canvas.fill(ui.__.windingRule)
|
|
9
|
-
|
|
9
|
+
ui.__.__font ? drawText(ui, canvas) : canvas.fill(ui.__.windingRule)
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function fills(ui: IUI, canvas: ILeaferCanvas, fills: ILeafPaint[]): void {
|
|
13
13
|
let item: ILeafPaint
|
|
14
|
-
const { windingRule } = ui.__
|
|
14
|
+
const { windingRule, __font } = ui.__
|
|
15
15
|
for (let i = 0, len = fills.length; i < len; i++) {
|
|
16
16
|
item = fills[i]
|
|
17
17
|
canvas.fillStyle = item.style
|
|
@@ -23,16 +23,21 @@ export function fills(ui: IUI, canvas: ILeaferCanvas, fills: ILeafPaint[]): void
|
|
|
23
23
|
canvas.transform(a, b, c, d, e, f)
|
|
24
24
|
|
|
25
25
|
if (item.blendMode) canvas.blendMode = item.blendMode
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
__font ? drawText(ui, canvas) : canvas.fill(windingRule)
|
|
27
28
|
|
|
28
29
|
canvas.restore()
|
|
29
30
|
} else {
|
|
30
31
|
if (item.blendMode) {
|
|
31
32
|
canvas.saveBlendMode(item.blendMode)
|
|
32
|
-
|
|
33
|
+
|
|
34
|
+
__font ? drawText(ui, canvas) : canvas.fill(windingRule)
|
|
35
|
+
|
|
33
36
|
canvas.restoreBlendMode()
|
|
34
37
|
} else {
|
|
35
|
-
|
|
38
|
+
|
|
39
|
+
__font ? drawText(ui, canvas) : canvas.fill(windingRule)
|
|
40
|
+
|
|
36
41
|
}
|
|
37
42
|
}
|
|
38
43
|
}
|
package/src/FillText.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ILeaferCanvas } from '@leafer/interface'
|
|
2
|
+
|
|
3
|
+
import { IUI, ITextRowData } from '@leafer-ui/interface'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export function drawText(ui: IUI, canvas: ILeaferCanvas): void {
|
|
7
|
+
|
|
8
|
+
let row: ITextRowData
|
|
9
|
+
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData
|
|
10
|
+
|
|
11
|
+
for (let i = 0, len = rows.length; i < len; i++) {
|
|
12
|
+
row = rows[i]
|
|
13
|
+
|
|
14
|
+
if (row.text) {
|
|
15
|
+
canvas.fillText(row.text, row.x, row.y)
|
|
16
|
+
} else if (row.data) {
|
|
17
|
+
row.data.forEach(charData => {
|
|
18
|
+
canvas.fillText(charData.char, charData.x, row.y)
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (decorationY) canvas.fillRect(row.x, row.y + decorationY, row.width, decorationHeight)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
}
|
package/src/Shape.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { BoundsHelper } from '@leafer/math'
|
|
|
3
3
|
|
|
4
4
|
import { IUI, ICachedShape } from '@leafer-ui/interface'
|
|
5
5
|
|
|
6
|
+
const { getSpread, getOuterOf, getByMove, getIntersectData } = BoundsHelper
|
|
6
7
|
|
|
7
8
|
export function shape(ui: IUI, current: ILeaferCanvas, options: IRenderOptions): ICachedShape {
|
|
8
9
|
const canvas = current.getSameCanvas()
|
|
@@ -15,8 +16,8 @@ export function shape(ui: IUI, current: ILeaferCanvas, options: IRenderOptions):
|
|
|
15
16
|
|
|
16
17
|
if (!current.bounds.includes(__world, options.matrix)) {
|
|
17
18
|
|
|
18
|
-
const {
|
|
19
|
-
const worldClipBounds =
|
|
19
|
+
const { shapeRenderSpreadWidth: spreadWidth } = ui.__layout
|
|
20
|
+
const worldClipBounds = getIntersectData(spreadWidth ? getSpread(current.bounds, spreadWidth * scaleX) : current.bounds, __world, options.matrix)
|
|
20
21
|
matrix = current.bounds.getFitMatrix(worldClipBounds)
|
|
21
22
|
|
|
22
23
|
if (matrix.a < 1) {
|
|
@@ -27,8 +28,8 @@ export function shape(ui: IUI, current: ILeaferCanvas, options: IRenderOptions):
|
|
|
27
28
|
scaleY *= matrix.d
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
shapeBounds =
|
|
31
|
-
bounds =
|
|
31
|
+
shapeBounds = getOuterOf(__world, matrix)
|
|
32
|
+
bounds = getByMove(shapeBounds, -matrix.e, -matrix.f)
|
|
32
33
|
|
|
33
34
|
if (options.matrix) matrix.multiply(options.matrix)
|
|
34
35
|
options = { ...options, matrix }
|
package/src/Stroke.ts
CHANGED
|
@@ -1,87 +1,105 @@
|
|
|
1
1
|
import { ILeaferCanvas } from '@leafer/interface'
|
|
2
2
|
|
|
3
3
|
import { IUI, ILeafStrokePaint, ILeafPaint } from '@leafer-ui/interface'
|
|
4
|
+
import { strokeText, strokesText } from './StrokeText'
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
export function stroke(ui: IUI, canvas: ILeaferCanvas, stroke: string | object): void {
|
|
7
8
|
const options = ui.__
|
|
8
|
-
const { strokeWidth, strokeAlign } = options
|
|
9
|
+
const { strokeWidth, strokeAlign, __font } = options
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
if (__font) {
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
canvas.setStroke(undefined, strokeWidth, options)
|
|
14
|
-
canvas.strokeStyle = stroke
|
|
15
|
-
canvas.stroke()
|
|
16
|
-
break
|
|
13
|
+
strokeText(ui, canvas, stroke)
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
canvas.save()
|
|
20
|
-
canvas.setStroke(undefined, strokeWidth * 2, options)
|
|
21
|
-
canvas.clip(options.windingRule)
|
|
15
|
+
} else {
|
|
22
16
|
|
|
23
|
-
|
|
24
|
-
canvas.stroke()
|
|
17
|
+
switch (strokeAlign) {
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
break
|
|
19
|
+
case 'center':
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
canvas.setStroke(stroke, strokeWidth, options)
|
|
22
|
+
canvas.stroke()
|
|
23
|
+
break
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
case 'inside':
|
|
34
26
|
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
canvas.save()
|
|
28
|
+
canvas.setStroke(stroke, strokeWidth * 2, options)
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
canvas.clip(options.windingRule)
|
|
31
|
+
canvas.stroke()
|
|
40
32
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
canvas.restore()
|
|
34
|
+
|
|
35
|
+
break
|
|
36
|
+
|
|
37
|
+
case 'outside':
|
|
38
|
+
const out = canvas.getSameCanvas(true)
|
|
39
|
+
out.setStroke(stroke, strokeWidth * 2, ui.__)
|
|
45
40
|
|
|
41
|
+
ui.__drawRenderPath(out)
|
|
42
|
+
|
|
43
|
+
out.stroke()
|
|
44
|
+
|
|
45
|
+
out.clip(options.windingRule)
|
|
46
|
+
out.clearWorld(ui.__layout.renderBounds)
|
|
47
|
+
|
|
48
|
+
canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds)
|
|
49
|
+
out.recycle()
|
|
50
|
+
|
|
51
|
+
break
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
}
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
export function strokes(ui: IUI, canvas: ILeaferCanvas, strokes: ILeafPaint[]): void {
|
|
49
58
|
const options = ui.__
|
|
50
|
-
const { strokeWidth, strokeAlign } = options
|
|
59
|
+
const { strokeWidth, strokeAlign, __font } = options
|
|
60
|
+
|
|
61
|
+
if (__font) {
|
|
62
|
+
|
|
63
|
+
strokesText(ui, canvas, strokes)
|
|
64
|
+
|
|
65
|
+
} else {
|
|
51
66
|
|
|
52
|
-
|
|
67
|
+
switch (strokeAlign) {
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
69
|
+
case 'center':
|
|
70
|
+
canvas.setStroke(undefined, strokeWidth, options)
|
|
71
|
+
drawStrokesStyle(strokes, canvas)
|
|
72
|
+
break
|
|
58
73
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
case 'inside':
|
|
75
|
+
canvas.save()
|
|
76
|
+
canvas.setStroke(undefined, strokeWidth * 2, options)
|
|
77
|
+
canvas.clip(options.windingRule)
|
|
63
78
|
|
|
64
|
-
|
|
79
|
+
drawStrokesStyle(strokes, canvas)
|
|
65
80
|
|
|
66
|
-
|
|
67
|
-
|
|
81
|
+
canvas.restore()
|
|
82
|
+
break
|
|
68
83
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
84
|
+
case 'outside':
|
|
85
|
+
const { renderBounds } = ui.__layout
|
|
86
|
+
const out = canvas.getSameCanvas(true)
|
|
87
|
+
ui.__drawRenderPath(out)
|
|
73
88
|
|
|
74
|
-
|
|
89
|
+
out.setStroke(undefined, strokeWidth * 2, ui.__)
|
|
75
90
|
|
|
76
|
-
|
|
91
|
+
drawStrokesStyle(strokes, out)
|
|
77
92
|
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
out.clip(options.windingRule)
|
|
94
|
+
out.clearWorld(renderBounds)
|
|
95
|
+
|
|
96
|
+
canvas.copyWorldToInner(out, ui.__world, renderBounds)
|
|
97
|
+
out.recycle()
|
|
98
|
+
break
|
|
99
|
+
}
|
|
80
100
|
|
|
81
|
-
canvas.copyWorldToInner(out, ui.__world, renderBounds)
|
|
82
|
-
out.recycle()
|
|
83
|
-
break
|
|
84
101
|
}
|
|
102
|
+
|
|
85
103
|
}
|
|
86
104
|
|
|
87
105
|
function drawStrokesStyle(strokes: ILeafStrokePaint[], canvas: ILeaferCanvas): void {
|
|
@@ -96,6 +114,7 @@ function drawStrokesStyle(strokes: ILeafStrokePaint[], canvas: ILeaferCanvas): v
|
|
|
96
114
|
// canvas.stroke()
|
|
97
115
|
// canvas.restore()
|
|
98
116
|
// } else {
|
|
117
|
+
|
|
99
118
|
if (item.blendMode) {
|
|
100
119
|
canvas.saveBlendMode(item.blendMode)
|
|
101
120
|
canvas.stroke()
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { ILeaferCanvas } from '@leafer/interface'
|
|
2
|
+
|
|
3
|
+
import { IUI, ITextRowData, ILeafStrokePaint, ILeafPaint, IStrokeAlign } from '@leafer-ui/interface'
|
|
4
|
+
import { drawText } from './FillText'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export function strokeText(ui: IUI, canvas: ILeaferCanvas, stroke: string | object): void {
|
|
8
|
+
const { strokeAlign } = ui.__
|
|
9
|
+
switch (strokeAlign) {
|
|
10
|
+
case 'center':
|
|
11
|
+
canvas.setStroke(stroke, ui.__.strokeWidth, ui.__)
|
|
12
|
+
drawTextStroke(ui, canvas)
|
|
13
|
+
break
|
|
14
|
+
case 'inside':
|
|
15
|
+
drawAlignStroke(ui, canvas, stroke, 'inside')
|
|
16
|
+
break
|
|
17
|
+
case 'outside':
|
|
18
|
+
drawAlignStroke(ui, canvas, stroke, 'outside')
|
|
19
|
+
break
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function drawAlignStroke(ui: IUI, canvas: ILeaferCanvas, stroke: string | object, align: IStrokeAlign): void {
|
|
24
|
+
const { strokeWidth, __font } = ui.__
|
|
25
|
+
|
|
26
|
+
const out = canvas.getSameCanvas(true)
|
|
27
|
+
out.setStroke(stroke, strokeWidth * 2, ui.__)
|
|
28
|
+
|
|
29
|
+
out.font = __font
|
|
30
|
+
drawTextStroke(ui, out)
|
|
31
|
+
|
|
32
|
+
out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in'
|
|
33
|
+
drawText(ui, out)
|
|
34
|
+
out.blendMode = 'normal'
|
|
35
|
+
|
|
36
|
+
canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds)
|
|
37
|
+
out.recycle()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function strokesText(ui: IUI, canvas: ILeaferCanvas, strokes: ILeafPaint[]): void {
|
|
41
|
+
const { strokeAlign } = ui.__
|
|
42
|
+
switch (strokeAlign) {
|
|
43
|
+
case 'center':
|
|
44
|
+
canvas.setStroke(undefined, ui.__.strokeWidth, ui.__)
|
|
45
|
+
drawStrokesStyle(ui, strokes, canvas)
|
|
46
|
+
break
|
|
47
|
+
case 'inside':
|
|
48
|
+
drawAlignStroke(ui, canvas, strokes, 'inside')
|
|
49
|
+
break
|
|
50
|
+
case 'outside':
|
|
51
|
+
drawAlignStrokes(ui, canvas, strokes, 'outside')
|
|
52
|
+
break
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
function drawAlignStrokes(ui: IUI, canvas: ILeaferCanvas, strokes: ILeafPaint[], align: IStrokeAlign): void {
|
|
58
|
+
const { strokeWidth, __font } = ui.__
|
|
59
|
+
|
|
60
|
+
const out = canvas.getSameCanvas(true)
|
|
61
|
+
out.setStroke(undefined, strokeWidth * 2, ui.__)
|
|
62
|
+
|
|
63
|
+
out.font = __font
|
|
64
|
+
drawStrokesStyle(ui, strokes, out)
|
|
65
|
+
|
|
66
|
+
out.blendMode = align === 'outside' ? 'destination - out' : 'destination -in '
|
|
67
|
+
drawText(ui, out)
|
|
68
|
+
out.blendMode = 'normal'
|
|
69
|
+
|
|
70
|
+
canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds)
|
|
71
|
+
out.recycle()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
function drawStrokesStyle(ui: IUI, strokes: ILeafStrokePaint[], canvas: ILeaferCanvas): void {
|
|
76
|
+
strokes.forEach((item: ILeafStrokePaint) => {
|
|
77
|
+
canvas.strokeStyle = item.style
|
|
78
|
+
|
|
79
|
+
// if (item.transform) {
|
|
80
|
+
// canvas.save()
|
|
81
|
+
// if (item.blendMode) canvas.blendMode = item.blendMode
|
|
82
|
+
// const { a, b, c, d, e, f } = item.transform
|
|
83
|
+
// canvas.transform(a, b, c, d, e, f)
|
|
84
|
+
// canvas.stroke()
|
|
85
|
+
// canvas.restore()
|
|
86
|
+
// } else {
|
|
87
|
+
|
|
88
|
+
if (item.blendMode) {
|
|
89
|
+
canvas.saveBlendMode(item.blendMode)
|
|
90
|
+
drawTextStroke(ui, canvas)
|
|
91
|
+
canvas.restoreBlendMode()
|
|
92
|
+
} else {
|
|
93
|
+
drawTextStroke(ui, canvas)
|
|
94
|
+
}
|
|
95
|
+
//}
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function drawTextStroke(ui: IUI, canvas: ILeaferCanvas): void {
|
|
100
|
+
|
|
101
|
+
let row: ITextRowData
|
|
102
|
+
const { rows, decorationY, decorationHeight } = ui.__.__textDrawData
|
|
103
|
+
|
|
104
|
+
for (let i = 0, len = rows.length; i < len; i++) {
|
|
105
|
+
row = rows[i]
|
|
106
|
+
|
|
107
|
+
if (row.text) {
|
|
108
|
+
canvas.strokeText(row.text, row.x, row.y)
|
|
109
|
+
} else if (row.data) {
|
|
110
|
+
row.data.forEach(charData => {
|
|
111
|
+
canvas.strokeText(charData.char, charData.x, row.y)
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (decorationY) canvas.strokeRect(row.x, row.y + decorationY, row.width, decorationHeight)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { fill, fills } from './Fill'
|
|
2
|
+
export { drawText } from './FillText'
|
|
2
3
|
export { stroke, strokes } from './Stroke'
|
|
4
|
+
export { strokeText, strokesText, drawTextStroke } from './StrokeText'
|
|
3
5
|
export { shape } from './Shape'
|
|
4
|
-
export { computeFill, computeStroke } from './Compute'
|
|
5
|
-
|
|
6
|
+
export { computeFill, computeStroke } from './Compute'
|
package/src/paint/conic.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IMatrixData, IPointData, IBoundsData } from '@leafer/interface'
|
|
2
|
+
import { IGradientPaint, ILeafPaint } from '@leafer-ui/interface'
|
|
2
3
|
import { Platform, PointHelper, MatrixHelper } from '@leafer/core'
|
|
3
4
|
import { applyStops } from './linear'
|
|
4
5
|
|
|
5
6
|
|
|
6
|
-
const { set, getAngle } = PointHelper
|
|
7
|
+
const { set, getAngle, getDistance } = PointHelper
|
|
7
8
|
const { get, rotateOf, scaleOf } = MatrixHelper
|
|
8
9
|
|
|
9
10
|
const defaultFrom = { x: 0.5, y: 0.5 }
|
|
@@ -12,15 +13,17 @@ const defaultTo = { x: 0.5, y: 1 }
|
|
|
12
13
|
const realFrom = {} as IPointData
|
|
13
14
|
const realTo = {} as IPointData
|
|
14
15
|
|
|
15
|
-
export function conicGradient(paint: IGradientPaint,
|
|
16
|
+
export function conicGradient(paint: IGradientPaint, box: IBoundsData): ILeafPaint {
|
|
16
17
|
|
|
17
18
|
let { from, to, type, opacity, blendMode, stretch } = paint
|
|
18
19
|
|
|
19
20
|
from || (from = defaultFrom)
|
|
20
21
|
to || (to = defaultTo)
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
const { x, y, width, height } = box
|
|
24
|
+
|
|
25
|
+
set(realFrom, x + from.x * width, y + from.y * height)
|
|
26
|
+
set(realTo, x + to.x * width, y + to.y * height)
|
|
24
27
|
|
|
25
28
|
const transform: IMatrixData = get()
|
|
26
29
|
const angle = getAngle(realFrom, realTo)
|
|
@@ -33,7 +36,7 @@ export function conicGradient(paint: IGradientPaint, width: number, height: numb
|
|
|
33
36
|
rotateOf(transform, realFrom, angle)
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
const style = Platform.canvas.createConicGradient(0, realFrom.x, realFrom.y)
|
|
39
|
+
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))
|
|
37
40
|
applyStops(style, paint.stops, opacity)
|
|
38
41
|
|
|
39
42
|
return {
|
package/src/paint/image.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { IBoundsData } from '@leafer/interface'
|
|
1
2
|
import { IUI, IImagePaint, ILeafPaint, IMatrixData, IImagePaintMode, IPointData } from '@leafer-ui/interface'
|
|
2
3
|
import { Platform, MatrixHelper, ImageEvent } from '@leafer/core'
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
const { get, rotateOf, translate, scaleOf, scale: scaleHelper, rotate } = MatrixHelper
|
|
6
7
|
|
|
7
|
-
export function image(ui: IUI, attrName: string, paint: IImagePaint,
|
|
8
|
+
export function image(ui: IUI, attrName: string, paint: IImagePaint, box: IBoundsData): ILeafPaint {
|
|
8
9
|
let { type, blendMode } = paint
|
|
9
10
|
let leaferPaint: ILeafPaint = {
|
|
10
11
|
type,
|
|
@@ -19,22 +20,26 @@ export function image(ui: IUI, attrName: string, paint: IImagePaint, boxWidth: n
|
|
|
19
20
|
let transform: IMatrixData
|
|
20
21
|
let { opacity, mode, offset, scale, rotation } = paint
|
|
21
22
|
let { width, height } = image
|
|
22
|
-
const sameBox =
|
|
23
|
+
const sameBox = box.width === width && box.height === height
|
|
23
24
|
|
|
24
25
|
switch (mode) {
|
|
25
26
|
case 'strench':
|
|
26
|
-
if (!sameBox) width =
|
|
27
|
+
if (!sameBox) width = box.width, height = box.height
|
|
28
|
+
if (box.x || box.y) {
|
|
29
|
+
transform = get()
|
|
30
|
+
translate(transform, box.x, box.y)
|
|
31
|
+
}
|
|
27
32
|
break
|
|
28
33
|
case 'clip':
|
|
29
|
-
if (offset || scale || rotation) transform =
|
|
34
|
+
if (offset || scale || rotation) transform = getClipTransform(box, offset, scale, rotation)
|
|
30
35
|
break
|
|
31
36
|
case 'repeat':
|
|
32
|
-
if (!sameBox || scale || rotation) transform = getRepeatTransform(width, height, scale as number, rotation)
|
|
37
|
+
if (!sameBox || scale || rotation) transform = getRepeatTransform(box, width, height, scale as number, rotation)
|
|
33
38
|
break
|
|
34
39
|
case 'fit':
|
|
35
40
|
case 'cover':
|
|
36
41
|
default:
|
|
37
|
-
if (!sameBox || rotation) transform = getFillOrFitTransform(mode, width, height,
|
|
42
|
+
if (!sameBox || rotation) transform = getFillOrFitTransform(mode, box, width, height, rotation)
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
leaferPaint.style = createPattern(image.getCanvas(width, height, opacity), transform, mode === 'repeat')
|
|
@@ -44,7 +49,7 @@ export function image(ui: IUI, attrName: string, paint: IImagePaint, boxWidth: n
|
|
|
44
49
|
image.load(() => {
|
|
45
50
|
if (!ui.__.__getInput('width')) ui.width = image.width
|
|
46
51
|
if (!ui.__.__getInput('height')) ui.height = image.height
|
|
47
|
-
ui.
|
|
52
|
+
ui.forceUpdate('width')
|
|
48
53
|
ui.emitEvent(new ImageEvent(ImageEvent.LOADED, ui, image, attrName, paint))
|
|
49
54
|
}, (error) => {
|
|
50
55
|
ui.emitEvent(new ImageEvent(ImageEvent.ERROR, ui, image, attrName, paint, error))
|
|
@@ -55,49 +60,48 @@ export function image(ui: IUI, attrName: string, paint: IImagePaint, boxWidth: n
|
|
|
55
60
|
return leaferPaint
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
function
|
|
59
|
-
const transform: IMatrixData = get()
|
|
60
|
-
if (offset) translate(transform, offset.x, offset.y)
|
|
61
|
-
if (scale) typeof scale === 'number' ? scaleHelper(transform, scale) : scaleHelper(transform, scale.x, scale.y)
|
|
62
|
-
if (rotation) rotate(transform, rotation)
|
|
63
|
-
return transform
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function getFillOrFitTransform(mode: IImagePaintMode, imageWidth: number, imageHeight: number, boxWidth: number, boxHeight: number, rotation: number): IMatrixData {
|
|
63
|
+
function getFillOrFitTransform(mode: IImagePaintMode, box: IBoundsData, width: number, height: number, rotation: number): IMatrixData {
|
|
67
64
|
const transform: IMatrixData = get()
|
|
68
65
|
const swap = rotation && rotation !== 180
|
|
69
|
-
const sw =
|
|
70
|
-
const sh =
|
|
66
|
+
const sw = box.width / (swap ? height : width)
|
|
67
|
+
const sh = box.height / (swap ? width : height)
|
|
71
68
|
const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh)
|
|
72
|
-
const x = (
|
|
73
|
-
const y = (
|
|
69
|
+
const x = box.x + (box.width - width * scale) / 2
|
|
70
|
+
const y = box.y + (box.height - height * scale) / 2
|
|
74
71
|
translate(transform, x, y)
|
|
75
72
|
scaleHelper(transform, scale)
|
|
76
|
-
if (rotation) {
|
|
77
|
-
const center = { x: boxWidth / 2, y: boxHeight / 2 }
|
|
78
|
-
rotateOf(transform, center, rotation)
|
|
79
|
-
}
|
|
73
|
+
if (rotation) rotateOf(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation)
|
|
80
74
|
return transform
|
|
81
75
|
}
|
|
82
76
|
|
|
77
|
+
function getClipTransform(box: IBoundsData, offset: IPointData, scale: number | IPointData, rotation: number): IMatrixData {
|
|
78
|
+
const transform: IMatrixData = get()
|
|
79
|
+
translate(transform, box.x, box.y)
|
|
80
|
+
if (offset) translate(transform, offset.x, offset.y)
|
|
81
|
+
if (scale) typeof scale === 'number' ? scaleHelper(transform, scale) : scaleHelper(transform, scale.x, scale.y)
|
|
82
|
+
if (rotation) rotate(transform, rotation)
|
|
83
|
+
return transform
|
|
84
|
+
}
|
|
83
85
|
|
|
84
|
-
function getRepeatTransform(
|
|
86
|
+
function getRepeatTransform(box: IBoundsData, width: number, height: number, scale: number, rotation: number): IMatrixData {
|
|
85
87
|
const transform = get()
|
|
88
|
+
|
|
86
89
|
if (rotation) {
|
|
87
90
|
rotate(transform, rotation)
|
|
88
91
|
switch (rotation) {
|
|
89
92
|
case 90:
|
|
90
|
-
translate(transform,
|
|
93
|
+
translate(transform, height, 0)
|
|
91
94
|
break
|
|
92
95
|
case 180:
|
|
93
|
-
translate(transform,
|
|
96
|
+
translate(transform, width, height)
|
|
94
97
|
break
|
|
95
98
|
case 270:
|
|
96
|
-
translate(transform, 0,
|
|
99
|
+
translate(transform, 0, width)
|
|
97
100
|
break
|
|
98
101
|
}
|
|
99
102
|
}
|
|
100
|
-
|
|
103
|
+
translate(transform, box.x, box.y)
|
|
104
|
+
if (scale) scaleOf(transform, box, scale)
|
|
101
105
|
return transform
|
|
102
106
|
}
|
|
103
107
|
|
package/src/paint/linear.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { IObject } from '@leafer/interface'
|
|
1
|
+
import { IObject, IBoundsData } from '@leafer/interface'
|
|
2
2
|
import { Platform } from '@leafer/core'
|
|
3
3
|
|
|
4
4
|
import { IGradientPaint, ILeafPaint, IColorStop } from '@leafer-ui/interface'
|
|
5
|
-
import {
|
|
5
|
+
import { ColorConvert } from '@leafer-ui/color'
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
const defaultFrom = { x: 0.5, y: 0 }
|
|
9
9
|
const defaultTo = { x: 0.5, y: 1 }
|
|
10
10
|
|
|
11
|
-
export function linearGradient(paint: IGradientPaint,
|
|
11
|
+
export function linearGradient(paint: IGradientPaint, box: IBoundsData): ILeafPaint {
|
|
12
12
|
|
|
13
13
|
let { from, to, type, blendMode, opacity } = paint
|
|
14
14
|
|
|
15
15
|
from || (from = defaultFrom)
|
|
16
16
|
to || (to = defaultTo)
|
|
17
17
|
|
|
18
|
-
const style = Platform.canvas.createLinearGradient(from.x * width, from.y * height, to.x * width, to.y * height)
|
|
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
19
|
applyStops(style, paint.stops, opacity)
|
|
20
20
|
|
|
21
21
|
return {
|
|
@@ -30,6 +30,6 @@ export function applyStops(gradient: IObject, stops: IColorStop[], opacity: numb
|
|
|
30
30
|
let stop: IColorStop
|
|
31
31
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
32
32
|
stop = stops[i]
|
|
33
|
-
gradient.addColorStop(stop.offset,
|
|
33
|
+
gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity))
|
|
34
34
|
}
|
|
35
35
|
}
|
package/src/paint/radial.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IBoundsData } from '@leafer/interface'
|
|
2
2
|
import { Platform, PointHelper, MatrixHelper } from '@leafer/core'
|
|
3
|
+
|
|
4
|
+
import { IGradientPaint, ILeafPaint, IMatrixData, IPointData } from '@leafer-ui/interface'
|
|
5
|
+
|
|
3
6
|
import { applyStops } from './linear'
|
|
4
7
|
|
|
5
8
|
|
|
@@ -12,17 +15,19 @@ const defaultTo = { x: 0.5, y: 1 }
|
|
|
12
15
|
const realFrom = {} as IPointData
|
|
13
16
|
const realTo = {} as IPointData
|
|
14
17
|
|
|
15
|
-
export function radialGradient(paint: IGradientPaint,
|
|
18
|
+
export function radialGradient(paint: IGradientPaint, box: IBoundsData): ILeafPaint {
|
|
16
19
|
|
|
17
20
|
let { from, to, type, opacity, blendMode, stretch } = paint
|
|
18
21
|
|
|
19
22
|
from || (from = defaultFrom)
|
|
20
23
|
to || (to = defaultTo)
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
set(
|
|
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)
|
|
24
28
|
|
|
25
29
|
let transform: IMatrixData
|
|
30
|
+
|
|
26
31
|
if (width !== height || stretch) {
|
|
27
32
|
transform = get()
|
|
28
33
|
scaleOf(transform, realFrom, width / height * (stretch || 1), 1)
|