@leafer-ui/paint 1.0.0-beta.8 → 1.0.0-rc.10

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 CHANGED
@@ -1,29 +1,32 @@
1
1
  {
2
2
  "name": "@leafer-ui/paint",
3
- "version": "1.0.0-beta.8",
3
+ "version": "1.0.0-rc.10",
4
4
  "description": "@leafer-ui/paint",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
7
7
  "main": "src/index.ts",
8
+ "types": "types/index.d.ts",
8
9
  "files": [
9
- "src"
10
+ "src",
11
+ "types",
12
+ "dist"
10
13
  ],
11
14
  "repository": {
12
15
  "type": "git",
13
16
  "url": "https://github.com/leaferjs/ui.git"
14
17
  },
15
- "homepage": "https://github.com/leaferjs/ui/tree/main/packages/paint",
18
+ "homepage": "https://github.com/leaferjs/ui/tree/main/packages/partner/paint",
16
19
  "bugs": "https://github.com/leaferjs/ui/issues",
17
20
  "keywords": [
18
21
  "leafer-ui",
19
22
  "leaferjs"
20
23
  ],
21
24
  "dependencies": {
22
- "@leafer/core": "1.0.0-beta.8",
23
- "@leafer-ui/color": "1.0.0-beta.8"
25
+ "@leafer/core": "1.0.0-rc.10",
26
+ "@leafer-ui/draw": "1.0.0-rc.10"
24
27
  },
25
28
  "devDependencies": {
26
- "@leafer/interface": "1.0.0-beta.8",
27
- "@leafer-ui/interface": "1.0.0-beta.8"
29
+ "@leafer/interface": "1.0.0-rc.10",
30
+ "@leafer-ui/interface": "1.0.0-rc.10"
28
31
  }
29
32
  }
package/src/Compute.ts CHANGED
@@ -1,35 +1,37 @@
1
- import { IUI, IPaint, ILeafPaint, IRGB } from '@leafer-ui/interface'
2
- import { ColorConvert } from '@leafer-ui/color'
1
+ import { IUI, IPaint, ILeafPaint, IRGB, IBooleanMap, IObject, IPaintAttr } from '@leafer-ui/interface'
2
+ import { ColorConvert } from '@leafer-ui/draw'
3
3
 
4
- import { image } from "./paint/image"
5
- import { linearGradient } from './paint/linear'
6
- import { radialGradient } from "./paint/radial"
7
- import { conicGradient } from "./paint/conic"
4
+ import { PaintImage, PaintGradient } from "@leafer-ui/external"
8
5
 
9
6
 
10
- export function computeFill(ui: IUI): void {
11
- compute(ui, 'fill')
12
- }
13
-
14
- export function computeStroke(ui: IUI): void {
15
- compute(ui, 'stroke')
16
- }
7
+ let recycleMap: IBooleanMap
17
8
 
18
- function compute(ui: IUI, attrName: string): void {
19
- let paints = ui.__.__input[attrName] as IPaint[]
9
+ export function compute(attrName: IPaintAttr, ui: IUI): void {
10
+ const data = ui.__, leafPaints: ILeafPaint[] = []
20
11
 
21
- let item: ILeafPaint
22
- const value: ILeafPaint[] = []
12
+ let paints: IPaint[] = data.__input[attrName], hasOpacityPixel: boolean
23
13
  if (!(paints instanceof Array)) paints = [paints]
24
14
 
25
- for (let i = 0, len = paints.length; i < len; i++) {
26
- item = getLeafPaint(ui, paints[i], attrName)
27
- if (item) value.push(item)
15
+ recycleMap = PaintImage.recycleImage(attrName, data)
16
+
17
+ for (let i = 0, len = paints.length, item: ILeafPaint; i < len; i++) {
18
+ item = getLeafPaint(attrName, paints[i], ui)
19
+ if (item) leafPaints.push(item)
20
+ }
21
+
22
+ (data as IObject)['_' + attrName] = leafPaints.length ? leafPaints : undefined
23
+
24
+ if (leafPaints.length && leafPaints[0].image) hasOpacityPixel = leafPaints[0].image.hasOpacityPixel
25
+
26
+ if (attrName === 'fill') {
27
+ data.__pixelFill = hasOpacityPixel
28
+ } else {
29
+ data.__pixelStroke = hasOpacityPixel
28
30
  }
29
- ui.__['_' + attrName] = value.length ? value : undefined
30
31
  }
31
32
 
32
- function getLeafPaint(ui: IUI, paint: IPaint, attrName: string): ILeafPaint {
33
+
34
+ function getLeafPaint(attrName: string, paint: IPaint, ui: IUI): ILeafPaint {
33
35
  if (typeof paint !== 'object' || paint.visible === false || paint.opacity === 0) return undefined
34
36
  const { boxBounds } = ui.__layout
35
37
 
@@ -38,13 +40,13 @@ function getLeafPaint(ui: IUI, paint: IPaint, attrName: string): ILeafPaint {
38
40
  let { type, blendMode, color, opacity } = paint
39
41
  return { type, blendMode, style: ColorConvert.string(color, opacity) }
40
42
  case 'image':
41
- return image(ui, attrName, paint, boxBounds)
43
+ return PaintImage.image(ui, attrName, paint, boxBounds, !recycleMap || !recycleMap[paint.url])
42
44
  case 'linear':
43
- return linearGradient(paint, boxBounds)
45
+ return PaintGradient.linearGradient(paint, boxBounds)
44
46
  case 'radial':
45
- return radialGradient(paint, boxBounds)
47
+ return PaintGradient.radialGradient(paint, boxBounds)
46
48
  case 'angular':
47
- return conicGradient(paint, boxBounds)
49
+ return PaintGradient.conicGradient(paint, boxBounds)
48
50
  default:
49
51
  return (paint as IRGB).r ? { type: 'solid', style: ColorConvert.string(paint) } : undefined
50
52
  }
package/src/Fill.ts CHANGED
@@ -1,44 +1,51 @@
1
1
  import { ILeaferCanvas } from '@leafer/interface'
2
2
 
3
3
  import { ILeafPaint, IUI } from '@leafer-ui/interface'
4
+ import { PaintImage } from "@leafer-ui/external"
4
5
 
5
- import { drawText } from './FillText'
6
+ import { fillText } from './FillText'
6
7
 
7
8
 
8
- export function fill(ui: IUI, canvas: ILeaferCanvas, fill: string | object): void {
9
+ export function fill(fill: string, ui: IUI, canvas: ILeaferCanvas): void {
9
10
  canvas.fillStyle = fill
10
- ui.__.__font ? drawText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill())
11
+ ui.__.__font ? fillText(ui, canvas) : (ui.__.windingRule ? canvas.fill(ui.__.windingRule) : canvas.fill())
11
12
  }
12
13
 
13
- export function fills(ui: IUI, canvas: ILeaferCanvas, fills: ILeafPaint[]): void {
14
+
15
+ export function fills(fills: ILeafPaint[], ui: IUI, canvas: ILeaferCanvas): void {
14
16
  let item: ILeafPaint
15
17
  const { windingRule, __font } = ui.__
16
18
  for (let i = 0, len = fills.length; i < len; i++) {
17
19
  item = fills[i]
18
- canvas.fillStyle = item.style
19
20
 
20
- if (item.transform) {
21
- canvas.save()
21
+ if (item.image && PaintImage.checkImage(ui, canvas, item, !__font)) continue
22
+
23
+ if (item.style) {
22
24
 
23
- const { a, b, c, d, e, f } = item.transform
24
- canvas.transform(a, b, c, d, e, f)
25
+ canvas.fillStyle = item.style
25
26
 
26
- if (item.blendMode) canvas.blendMode = item.blendMode
27
+ if (item.transform) {
28
+ canvas.save()
27
29
 
28
- __font ? drawText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill())
30
+ canvas.transform(item.transform)
29
31
 
30
- canvas.restore()
31
- } else {
32
- if (item.blendMode) {
33
- canvas.saveBlendMode(item.blendMode)
32
+ if (item.blendMode) canvas.blendMode = item.blendMode
34
33
 
35
- __font ? drawText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill())
34
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill())
36
35
 
37
- canvas.restoreBlendMode()
36
+ canvas.restore()
38
37
  } else {
38
+ if (item.blendMode) {
39
+ canvas.saveBlendMode(item.blendMode)
40
+
41
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill())
42
+
43
+ canvas.restoreBlendMode()
44
+ } else {
39
45
 
40
- __font ? drawText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill())
46
+ __font ? fillText(ui, canvas) : (windingRule ? canvas.fill(windingRule) : canvas.fill())
41
47
 
48
+ }
42
49
  }
43
50
  }
44
51
 
package/src/FillText.ts CHANGED
@@ -3,7 +3,7 @@ import { ILeaferCanvas } from '@leafer/interface'
3
3
  import { IUI, ITextRowData } from '@leafer-ui/interface'
4
4
 
5
5
 
6
- export function drawText(ui: IUI, canvas: ILeaferCanvas): void {
6
+ export function fillText(ui: IUI, canvas: ILeaferCanvas): void {
7
7
 
8
8
  let row: ITextRowData
9
9
  const { rows, decorationY, decorationHeight } = ui.__.__textDrawData
package/src/Shape.ts CHANGED
@@ -8,50 +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, matrix: IMatrix, shapeBounds: IBoundsData
13
- let worldCanvas: ILeaferCanvas
13
+ let bounds: IBoundsData, fitMatrix: IMatrix, shapeBounds: IBoundsData, worldCanvas: ILeaferCanvas
14
14
 
15
- const { __world } = ui
16
- let { a: scaleX, d: scaleY } = __world
15
+ let { scaleX, scaleY } = nowWorld
16
+ if (scaleX < 0) scaleX = -scaleX
17
+ if (scaleY < 0) scaleY = -scaleY
17
18
 
18
- if (!current.bounds.includes(__world, options.matrix)) {
19
+ if (current.bounds.includes(nowWorld)) {
20
+
21
+ worldCanvas = canvas
22
+ bounds = shapeBounds = nowWorld
23
+
24
+ } else {
19
25
 
20
26
  const { renderShapeSpread: spread } = ui.__layout
21
- const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX) : current.bounds, __world, options.matrix)
22
- matrix = current.bounds.getFitMatrix(worldClipBounds)
27
+ const worldClipBounds = getIntersectData(spread ? getSpread(current.bounds, spread * scaleX, spread * scaleY) : current.bounds, nowWorld)
28
+ fitMatrix = current.bounds.getFitMatrix(worldClipBounds)
29
+ let { a: fitScaleX, d: fitScaleY } = fitMatrix
23
30
 
24
- if (matrix.a < 1) {
31
+ if (fitMatrix.a < 1) {
25
32
  worldCanvas = current.getSameCanvas()
26
33
  ui.__renderShape(worldCanvas, options)
27
34
 
28
- scaleX *= matrix.a
29
- scaleY *= matrix.d
35
+ scaleX *= fitScaleX
36
+ scaleY *= fitScaleY
30
37
  }
31
38
 
32
- shapeBounds = getOuterOf(__world, matrix)
33
- bounds = getByMove(shapeBounds, -matrix.e, -matrix.f)
34
-
35
- if (options.matrix) matrix.multiply(options.matrix)
36
- options = { ...options, matrix }
37
-
38
- } else {
39
+ shapeBounds = getOuterOf(nowWorld, fitMatrix)
40
+ bounds = getByMove(shapeBounds, -fitMatrix.e, -fitMatrix.f)
39
41
 
40
42
  if (options.matrix) {
41
- scaleX *= options.matrix.a
42
- scaleY *= options.matrix.d
43
- bounds = shapeBounds = getOuterOf(__world, options.matrix)
44
- } else {
45
- bounds = shapeBounds = __world
43
+ const { matrix } = options
44
+ fitMatrix.multiply(matrix)
45
+ fitScaleX *= matrix.scaleX
46
+ fitScaleY *= matrix.scaleY
46
47
  }
47
48
 
48
- worldCanvas = canvas
49
+ options = { ...options, matrix: fitMatrix.withScale(fitScaleX, fitScaleY) }
50
+
49
51
  }
50
52
 
51
53
  ui.__renderShape(canvas, options)
52
54
 
53
55
  return {
54
- canvas, matrix, bounds,
56
+ canvas, matrix: fitMatrix, bounds,
55
57
  worldCanvas, shapeBounds, scaleX, scaleY
56
58
  }
57
59
  }
package/src/Stroke.ts CHANGED
@@ -1,18 +1,18 @@
1
1
  import { ILeaferCanvas } from '@leafer/interface'
2
2
 
3
- import { IUI, ILeafStrokePaint, ILeafPaint } from '@leafer-ui/interface'
3
+ import { IUI, ILeafPaint } from '@leafer-ui/interface'
4
4
 
5
- import { strokeText, strokesText } from './StrokeText'
5
+ import { strokeText, drawStrokesStyle } from './StrokeText'
6
6
 
7
7
 
8
- export function stroke(ui: IUI, canvas: ILeaferCanvas, stroke: string | object): void {
8
+ export function stroke(stroke: string, ui: IUI, canvas: ILeaferCanvas): void {
9
9
  const options = ui.__
10
- const { strokeWidth, strokeAlign, __font } = options
11
- if (!strokeWidth) return
10
+ const { __strokeWidth, strokeAlign, __font } = options
11
+ if (!__strokeWidth) return
12
12
 
13
13
  if (__font) {
14
14
 
15
- strokeText(ui, canvas, stroke)
15
+ strokeText(stroke, ui, canvas)
16
16
 
17
17
  } else {
18
18
 
@@ -20,16 +20,16 @@ export function stroke(ui: IUI, canvas: ILeaferCanvas, stroke: string | object):
20
20
 
21
21
  case 'center':
22
22
 
23
- canvas.setStroke(stroke, strokeWidth, options)
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, strokeWidth * 2, options)
30
+ canvas.setStroke(stroke, __strokeWidth * 2, options)
31
31
 
32
- canvas.clip(options.windingRule)
32
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip()
33
33
  canvas.stroke()
34
34
 
35
35
  canvas.restore()
@@ -37,85 +37,80 @@ export function stroke(ui: IUI, canvas: ILeaferCanvas, stroke: string | object):
37
37
  break
38
38
 
39
39
  case 'outside':
40
- const out = canvas.getSameCanvas(true)
41
- out.setStroke(stroke, strokeWidth * 2, ui.__)
40
+ const out = canvas.getSameCanvas(true, true)
41
+ out.setStroke(stroke, __strokeWidth * 2, options)
42
42
 
43
43
  ui.__drawRenderPath(out)
44
44
 
45
45
  out.stroke()
46
46
 
47
- out.clip(options.windingRule)
47
+ options.windingRule ? out.clip(options.windingRule) : out.clip()
48
48
  out.clearWorld(ui.__layout.renderBounds)
49
49
 
50
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds)
51
- out.recycle()
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
 
56
60
  }
57
61
  }
58
62
 
59
- export function strokes(ui: IUI, canvas: ILeaferCanvas, strokes: ILeafPaint[]): void {
63
+
64
+ export function strokes(strokes: ILeafPaint[], ui: IUI, canvas: ILeaferCanvas): void {
60
65
  const options = ui.__
61
- const { strokeWidth, strokeAlign, __font } = options
62
- if (!strokeWidth) return
66
+ const { __strokeWidth, strokeAlign, __font } = options
67
+ if (!__strokeWidth) return
63
68
 
64
69
  if (__font) {
65
70
 
66
- strokesText(ui, canvas, strokes)
71
+ strokeText(strokes, ui, canvas)
67
72
 
68
73
  } else {
69
74
 
70
75
  switch (strokeAlign) {
71
76
 
72
77
  case 'center':
73
- canvas.setStroke(undefined, strokeWidth, options)
74
- drawStrokesStyle(strokes, canvas)
78
+ canvas.setStroke(undefined, __strokeWidth, options)
79
+ drawStrokesStyle(strokes, false, ui, canvas)
75
80
  break
76
81
 
77
82
  case 'inside':
78
83
  canvas.save()
79
- canvas.setStroke(undefined, strokeWidth * 2, options)
80
- canvas.clip(options.windingRule)
84
+ canvas.setStroke(undefined, __strokeWidth * 2, options)
85
+ options.windingRule ? canvas.clip(options.windingRule) : canvas.clip()
81
86
 
82
- drawStrokesStyle(strokes, canvas)
87
+ drawStrokesStyle(strokes, false, ui, canvas)
83
88
 
84
89
  canvas.restore()
85
90
  break
86
91
 
87
92
  case 'outside':
88
93
  const { renderBounds } = ui.__layout
89
- const out = canvas.getSameCanvas(true)
94
+ const out = canvas.getSameCanvas(true, true)
90
95
  ui.__drawRenderPath(out)
91
96
 
92
- out.setStroke(undefined, strokeWidth * 2, ui.__)
97
+ out.setStroke(undefined, __strokeWidth * 2, options)
93
98
 
94
- drawStrokesStyle(strokes, out)
99
+ drawStrokesStyle(strokes, false, ui, out)
95
100
 
96
- out.clip(options.windingRule)
101
+ options.windingRule ? out.clip(options.windingRule) : out.clip()
97
102
  out.clearWorld(renderBounds)
98
103
 
99
- canvas.copyWorldToInner(out, ui.__world, renderBounds)
100
- out.recycle()
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)
101
111
  break
102
112
  }
103
113
 
104
114
  }
105
115
 
106
116
  }
107
-
108
- function drawStrokesStyle(strokes: ILeafStrokePaint[], canvas: ILeaferCanvas): void {
109
- strokes.forEach((item: ILeafStrokePaint) => {
110
- canvas.strokeStyle = item.style
111
-
112
- if (item.blendMode) {
113
- canvas.saveBlendMode(item.blendMode)
114
- canvas.stroke()
115
- canvas.restoreBlendMode()
116
- } else {
117
- canvas.stroke()
118
- }
119
-
120
- })
121
- }
package/src/StrokeText.ts CHANGED
@@ -1,91 +1,48 @@
1
1
  import { ILeaferCanvas } from '@leafer/interface'
2
2
 
3
- import { IUI, ITextRowData, ILeafStrokePaint, ILeafPaint, IStrokeAlign } from '@leafer-ui/interface'
3
+ import { IUI, ITextRowData, ILeafPaint, IStrokeAlign, ILeafStrokePaint } from '@leafer-ui/interface'
4
+ import { PaintImage } from "@leafer-ui/external"
4
5
 
5
- import { drawText } from './FillText'
6
+ import { fillText } from './FillText'
6
7
 
7
8
 
8
- export function strokeText(ui: IUI, canvas: ILeaferCanvas, stroke: string | object): void {
9
+ export function strokeText(stroke: string | ILeafPaint[], ui: IUI, canvas: ILeaferCanvas): void {
9
10
  const { strokeAlign } = ui.__
11
+ const isStrokes = typeof stroke !== 'string'
10
12
  switch (strokeAlign) {
11
13
  case 'center':
12
- canvas.setStroke(stroke, ui.__.strokeWidth, ui.__)
13
- drawTextStroke(ui, canvas)
14
+ canvas.setStroke(isStrokes ? undefined : stroke, ui.__.strokeWidth, ui.__)
15
+ isStrokes ? drawStrokesStyle(stroke as ILeafPaint[], true, ui, canvas) : drawTextStroke(ui, canvas)
14
16
  break
15
17
  case 'inside':
16
- drawAlignStroke(ui, canvas, stroke, 'inside')
18
+ drawAlignStroke('inside', stroke, isStrokes, ui, canvas)
17
19
  break
18
20
  case 'outside':
19
- drawAlignStroke(ui, canvas, stroke, 'outside')
21
+ drawAlignStroke('outside', stroke, isStrokes, ui, canvas)
20
22
  break
21
23
  }
22
24
  }
23
25
 
24
- function drawAlignStroke(ui: IUI, canvas: ILeaferCanvas, stroke: string | object, align: IStrokeAlign): void {
25
- const { strokeWidth, __font } = ui.__
26
+ function drawAlignStroke(align: IStrokeAlign, stroke: string | ILeafPaint[], isStrokes: boolean, ui: IUI, canvas: ILeaferCanvas): void {
27
+ const { __strokeWidth, __font } = ui.__
26
28
 
27
- const out = canvas.getSameCanvas(true)
28
- out.setStroke(stroke, strokeWidth * 2, ui.__)
29
+ const out = canvas.getSameCanvas(true, true)
30
+ out.setStroke(isStrokes ? undefined : stroke, __strokeWidth * 2, ui.__)
29
31
 
30
32
  out.font = __font
31
- drawTextStroke(ui, out)
33
+ isStrokes ? drawStrokesStyle(stroke as ILeafPaint[], true, ui, out) : drawTextStroke(ui, out)
32
34
 
33
35
  out.blendMode = align === 'outside' ? 'destination-out' : 'destination-in'
34
- drawText(ui, out)
36
+ fillText(ui, out)
35
37
  out.blendMode = 'normal'
36
38
 
37
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds)
38
- out.recycle()
39
- }
40
-
41
- export function strokesText(ui: IUI, canvas: ILeaferCanvas, strokes: ILeafPaint[]): void {
42
- const { strokeAlign } = ui.__
43
- switch (strokeAlign) {
44
- case 'center':
45
- canvas.setStroke(undefined, ui.__.strokeWidth, ui.__)
46
- drawStrokesStyle(ui, strokes, canvas)
47
- break
48
- case 'inside':
49
- drawAlignStroke(ui, canvas, strokes, 'inside')
50
- break
51
- case 'outside':
52
- drawAlignStrokes(ui, canvas, strokes, 'outside')
53
- break
39
+ if (ui.__worldFlipped) {
40
+ canvas.copyWorldByReset(out, ui.__nowWorld)
41
+ } else {
42
+ canvas.copyWorldToInner(out, ui.__nowWorld, ui.__layout.renderBounds)
54
43
  }
55
- }
56
-
57
-
58
- function drawAlignStrokes(ui: IUI, canvas: ILeaferCanvas, strokes: ILeafPaint[], align: IStrokeAlign): void {
59
- const { strokeWidth, __font } = ui.__
60
-
61
- const out = canvas.getSameCanvas(true)
62
- out.setStroke(undefined, strokeWidth * 2, ui.__)
63
-
64
- out.font = __font
65
- drawStrokesStyle(ui, strokes, out)
66
44
 
67
- out.blendMode = align === 'outside' ? 'destination - out' : 'destination -in '
68
- drawText(ui, out)
69
- out.blendMode = 'normal'
70
-
71
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds)
72
- out.recycle()
73
- }
74
-
75
-
76
- function drawStrokesStyle(ui: IUI, strokes: ILeafStrokePaint[], canvas: ILeaferCanvas): void {
77
- strokes.forEach((item: ILeafStrokePaint) => {
78
- canvas.strokeStyle = item.style
79
-
80
- if (item.blendMode) {
81
- canvas.saveBlendMode(item.blendMode)
82
- drawTextStroke(ui, canvas)
83
- canvas.restoreBlendMode()
84
- } else {
85
- drawTextStroke(ui, canvas)
86
- }
87
-
88
- })
45
+ out.recycle(ui.__nowWorld)
89
46
  }
90
47
 
91
48
  export function drawTextStroke(ui: IUI, canvas: ILeaferCanvas): void {
@@ -108,3 +65,25 @@ export function drawTextStroke(ui: IUI, canvas: ILeaferCanvas): void {
108
65
  }
109
66
 
110
67
  }
68
+
69
+ export function drawStrokesStyle(strokes: ILeafStrokePaint[], isText: boolean, ui: IUI, canvas: ILeaferCanvas): void {
70
+ let item: ILeafStrokePaint
71
+ for (let i = 0, len = strokes.length; i < len; i++) {
72
+ item = strokes[i]
73
+
74
+ if (item.image && PaintImage.checkImage(ui, canvas, item, false)) continue
75
+
76
+ if (item.style) {
77
+
78
+ canvas.strokeStyle = item.style
79
+
80
+ if (item.blendMode) {
81
+ canvas.saveBlendMode(item.blendMode)
82
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke()
83
+ canvas.restoreBlendMode()
84
+ } else {
85
+ isText ? drawTextStroke(ui, canvas) : canvas.stroke()
86
+ }
87
+ }
88
+ }
89
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,21 @@
1
- export { fill, fills } from './Fill'
2
- export { drawText } from './FillText'
3
- export { stroke, strokes } from './Stroke'
4
- export { strokeText, strokesText, drawTextStroke } from './StrokeText'
5
- export { shape } from './Shape'
6
- export { computeFill, computeStroke } from './Compute'
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
+ }
@@ -0,0 +1,5 @@
1
+ import { IPaintModule } from '@leafer-ui/interface';
2
+
3
+ declare const PaintModule: IPaintModule;
4
+
5
+ export { PaintModule };
@@ -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
- }
@@ -1,139 +0,0 @@
1
- import { IBoundsData, ISizeData } from '@leafer/interface'
2
- import { Platform, MatrixHelper, ImageEvent } from '@leafer/core'
3
-
4
- import { IUI, IImagePaint, ILeafPaint, IMatrixData, IImagePaintMode, IPointData } from '@leafer-ui/interface'
5
-
6
-
7
- const { get, rotateOfOuter, translate, scaleOfOuter, scale: scaleHelper, rotate } = MatrixHelper
8
-
9
- export function image(ui: IUI, attrName: string, paint: IImagePaint, box: IBoundsData): ILeafPaint {
10
- const { type, blendMode } = paint
11
- let leaferPaint: ILeafPaint = { type, style: 'rgba(255,255,255,0)' }
12
- if (blendMode) leaferPaint.blendMode = blendMode
13
-
14
- const { imageManager } = ui.leafer
15
- const image = imageManager.get(paint)
16
-
17
- if (image.ready) {
18
-
19
- if (hasSize(ui, attrName, image)) {
20
-
21
- let transform: IMatrixData
22
- let { opacity, mode, offset, scale, rotation } = paint
23
- let { width, height } = image
24
- const sameBox = box.width === width && box.height === height
25
-
26
- switch (mode) {
27
- case 'strench':
28
- if (!sameBox) width = box.width, height = box.height
29
- if (box.x || box.y) {
30
- transform = get()
31
- translate(transform, box.x, box.y)
32
- }
33
- break
34
- case 'clip':
35
- if (offset || scale || rotation) transform = getClipTransform(box, offset, scale, rotation)
36
- break
37
- case 'repeat':
38
- if (!sameBox || scale || rotation) transform = getRepeatTransform(box, width, height, scale as number, rotation)
39
- break
40
- case 'fit':
41
- case 'cover':
42
- default:
43
- if (!sameBox || rotation) transform = getFillOrFitTransform(mode, box, width, height, rotation)
44
- }
45
-
46
- leaferPaint.style = createPattern(image.getCanvas(width, height, opacity), transform, mode === 'repeat')
47
-
48
- }
49
-
50
- } else {
51
-
52
- imageManager.load(image,
53
- () => {
54
- if (ui.leafer) {
55
- if (hasSize(ui, attrName, image)) ui.forceUpdate('width')
56
- ui.emitEvent(new ImageEvent(ImageEvent.LOADED, ui, image, attrName, paint))
57
- }
58
- },
59
- (error) => {
60
- ui.emitEvent(new ImageEvent(ImageEvent.ERROR, ui, image, attrName, paint, error))
61
- }
62
- )
63
-
64
- }
65
-
66
- return leaferPaint
67
- }
68
-
69
- function hasSize(ui: IUI, attrName: string, image: ISizeData): boolean {
70
- const { __: data } = ui
71
-
72
- if (attrName === 'fill' && data) {
73
- if (!data.__naturalWidth || !data.__naturalHeight) {
74
- data.__naturalWidth = image.width
75
- data.__naturalHeight = image.height
76
- if (!data.__getInput('width') || !data.__getInput('height')) {
77
- ui.forceUpdate('width')
78
- return false
79
- }
80
- }
81
- }
82
-
83
- return true
84
- }
85
-
86
- function getFillOrFitTransform(mode: IImagePaintMode, box: IBoundsData, width: number, height: number, rotation: number): IMatrixData {
87
- const transform: IMatrixData = get()
88
- const swap = rotation && rotation !== 180
89
- const sw = box.width / (swap ? height : width)
90
- const sh = box.height / (swap ? width : height)
91
- const scale = mode === 'fit' ? Math.min(sw, sh) : Math.max(sw, sh)
92
- const x = box.x + (box.width - width * scale) / 2
93
- const y = box.y + (box.height - height * scale) / 2
94
- translate(transform, x, y)
95
- scaleHelper(transform, scale)
96
- if (rotation) rotateOfOuter(transform, { x: box.x + box.width / 2, y: box.y + box.height / 2 }, rotation)
97
- return transform
98
- }
99
-
100
- function getClipTransform(box: IBoundsData, offset: IPointData, scale: number | IPointData, rotation: number): IMatrixData {
101
- const transform: IMatrixData = get()
102
- translate(transform, box.x, box.y)
103
- if (offset) translate(transform, offset.x, offset.y)
104
- if (scale) typeof scale === 'number' ? scaleHelper(transform, scale) : scaleHelper(transform, scale.x, scale.y)
105
- if (rotation) rotate(transform, rotation)
106
- return transform
107
- }
108
-
109
- function getRepeatTransform(box: IBoundsData, width: number, height: number, scale: number, rotation: number): IMatrixData {
110
- const transform = get()
111
-
112
- if (rotation) {
113
- rotate(transform, rotation)
114
- switch (rotation) {
115
- case 90:
116
- translate(transform, height, 0)
117
- break
118
- case 180:
119
- translate(transform, width, height)
120
- break
121
- case 270:
122
- translate(transform, 0, width)
123
- break
124
- }
125
- }
126
- translate(transform, box.x, box.y)
127
- if (scale) scaleOfOuter(transform, box, scale)
128
- return transform
129
- }
130
-
131
-
132
- function createPattern(canvas: any, transform?: IMatrixData, repeat?: boolean,): CanvasPattern {
133
- let style = Platform.canvas.createPattern(canvas, repeat ? 'repeat' : 'no-repeat')
134
- if (transform) {
135
- const { a, b, c, d, e, f } = transform
136
- style.setTransform(new DOMMatrix([a, b, c, d, e, f]))
137
- }
138
- return style
139
- }
@@ -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/color'
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
- }
@@ -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
- }