@leafer-ui/paint 1.0.0-beta.10 → 1.0.0-beta.12

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer-ui/paint",
3
- "version": "1.0.0-beta.10",
3
+ "version": "1.0.0-beta.12",
4
4
  "description": "@leafer-ui/paint",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
@@ -19,11 +19,11 @@
19
19
  "leaferjs"
20
20
  ],
21
21
  "dependencies": {
22
- "@leafer/core": "1.0.0-beta.10",
23
- "@leafer-ui/color": "1.0.0-beta.10"
22
+ "@leafer/core": "1.0.0-beta.12",
23
+ "@leafer-ui/color": "1.0.0-beta.12"
24
24
  },
25
25
  "devDependencies": {
26
- "@leafer/interface": "1.0.0-beta.10",
27
- "@leafer-ui/interface": "1.0.0-beta.10"
26
+ "@leafer/interface": "1.0.0-beta.12",
27
+ "@leafer-ui/interface": "1.0.0-beta.12"
28
28
  }
29
29
  }
package/src/Compute.ts CHANGED
@@ -5,6 +5,7 @@ import { image } from "./paint/image/image"
5
5
  import { linearGradient } from './paint/linear'
6
6
  import { radialGradient } from "./paint/radial"
7
7
  import { conicGradient } from "./paint/conic"
8
+ import { recycleImage } from './paint/image'
8
9
 
9
10
 
10
11
  let recycleMap: IBooleanMap
@@ -16,7 +17,7 @@ export function compute(ui: IUI, attrName: string): void {
16
17
 
17
18
  if (!(paints instanceof Array)) paints = [paints]
18
19
 
19
- recycleMap = ui.__.__recycleImage(attrName)
20
+ recycleMap = recycleImage(ui.__, attrName)
20
21
 
21
22
  for (let i = 0, len = paints.length; i < len; i++) {
22
23
  item = getLeafPaint(ui, paints[i], attrName)
package/src/index.ts CHANGED
@@ -3,4 +3,5 @@ export { fillText } from './FillText'
3
3
  export { stroke, strokes } from './Stroke'
4
4
  export { strokeText, drawTextStroke } from './StrokeText'
5
5
  export { shape } from './Shape'
6
- export { compute } from './Compute'
6
+ export { compute } from './Compute'
7
+ export { recycleImage } from './paint/image'
@@ -8,16 +8,17 @@ import { createPattern } from './pattern'
8
8
 
9
9
 
10
10
  export function checkImage(ui: IUI, canvas: ILeaferCanvas, paint: ILeafPaint, allowPaint?: boolean): boolean {
11
- let { width, height } = ui.__world
11
+ const { scaleX, scaleY } = ui.__world
12
12
 
13
- if (!paint.data || paint.patternId === width + height) {
13
+ if (!paint.data || paint.patternId === scaleX + scaleY) {
14
14
  return false
15
15
  } else {
16
16
 
17
17
  if (allowPaint) {
18
18
  if (paint.image.isSVG && paint.data.mode !== 'repeat') {
19
- width *= canvas.pixelRatio
20
- height *= canvas.pixelRatio
19
+ let { width, height } = paint.data
20
+ width *= scaleX * canvas.pixelRatio
21
+ height *= scaleY * canvas.pixelRatio
21
22
  allowPaint = width > 4096 || height > 4096
22
23
  } else {
23
24
  allowPaint = false
@@ -35,12 +36,13 @@ export function checkImage(ui: IUI, canvas: ILeaferCanvas, paint: ILeafPaint, al
35
36
  canvas.restore()
36
37
  return true
37
38
  } else {
38
- ImageManager.patternTasker.addParallel(() => {
39
- if (canvas.bounds.hit(ui.__world)) {
40
- createPattern(ui, paint, canvas.pixelRatio)
41
- ui.forceUpdate('surface')
42
- }
43
- }, null, true)
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
+ }
44
46
  return false
45
47
  }
46
48
  }
@@ -1,15 +1,14 @@
1
1
  import { IBoundsData, ILeaferImage } from '@leafer/interface'
2
2
  import { MatrixHelper } from '@leafer/core'
3
3
 
4
- import { IUI, IImagePaint, ILeafPaint, ILeafPaintPatternData } from '@leafer-ui/interface'
4
+ import { IImagePaint, ILeafPaint, ILeafPaintPatternData } from '@leafer-ui/interface'
5
5
 
6
6
  import { clipMode, fillOrFitMode, repeatMode } from './mode'
7
- import { createPattern } from './pattern'
8
7
 
9
8
 
10
9
  const { get, translate } = MatrixHelper
11
10
 
12
- export function createData(ui: IUI, leafPaint: ILeafPaint, image: ILeaferImage, paint: IImagePaint, box: IBoundsData): void {
11
+ export function createData(leafPaint: ILeafPaint, image: ILeaferImage, paint: IImagePaint, box: IBoundsData): void {
13
12
  let { width, height } = image
14
13
 
15
14
  const { opacity, mode, offset, scale, rotation, blendMode } = paint
@@ -41,7 +40,4 @@ export function createData(ui: IUI, leafPaint: ILeafPaint, image: ILeaferImage,
41
40
  data.width = width
42
41
  data.height = height
43
42
  if (opacity) data.opacity = opacity
44
-
45
- const canvas = ui.leafer && ui.leafer.canvas
46
- if (canvas && canvas.bounds.hit(ui.__world)) createPattern(ui, leafPaint, canvas.pixelRatio)
47
43
  }
@@ -6,51 +6,51 @@ import { IUI, IImagePaint, ILeafPaint } from '@leafer-ui/interface'
6
6
  import { createData } from './data'
7
7
 
8
8
 
9
- export function image(ui: IUI, attrName: string, attrValue: IImagePaint, box: IBoundsData, first: boolean): ILeafPaint {
9
+ export function image(ui: IUI, attrName: string, attrValue: IImagePaint, box: IBoundsData, firstUse: boolean): ILeafPaint {
10
10
  const leafPaint: ILeafPaint = { type: attrValue.type }
11
11
  const image = leafPaint.image = ImageManager.get(attrValue)
12
12
 
13
- if (image.ready && hasNaturalSize(ui, attrName, image)) createData(ui, leafPaint, image, attrValue, box)
13
+ const event: IImageEvent = (firstUse || image.loading) && { target: ui, image, attrName, attrValue }
14
14
 
15
- if (first) {
15
+ if (image.ready) {
16
16
 
17
- const event: IImageEvent = { target: ui, image, attrName, attrValue }
18
-
19
- if (image.ready) {
17
+ if (hasNaturalSize(ui, attrName, image)) createData(leafPaint, image, attrValue, box)
20
18
 
19
+ if (firstUse) {
21
20
  emit(ImageEvent.LOAD, event)
22
21
  emit(ImageEvent.LOADED, event)
22
+ }
23
23
 
24
- } else if (image.error) {
24
+ } else if (image.error) {
25
25
 
26
+ if (firstUse) {
26
27
  ui.forceUpdate('surface')
27
28
  event.error = image.error
28
29
  emit(ImageEvent.ERROR, event)
30
+ }
29
31
 
30
- } else {
31
-
32
- emit(ImageEvent.LOAD, event)
32
+ } else {
33
33
 
34
- leafPaint.loadId = image.load(
35
- () => {
36
- if (ui.__) {
34
+ if (firstUse) emit(ImageEvent.LOAD, event)
37
35
 
38
- if (hasNaturalSize(ui, attrName, image)) {
39
- createData(ui, leafPaint, image, attrValue, box)
40
- ui.forceUpdate('surface')
41
- }
36
+ leafPaint.loadId = image.load(
37
+ () => {
38
+ if (!ui.destroyed) {
42
39
 
43
- emit(ImageEvent.LOADED, event)
40
+ if (hasNaturalSize(ui, attrName, image)) {
41
+ createData(leafPaint, image, attrValue, box)
42
+ ui.forceUpdate('surface')
44
43
  }
45
- },
46
- (error) => {
47
- ui.forceUpdate('surface')
48
- event.error = error
49
- emit(ImageEvent.ERROR, event)
50
- }
51
- )
52
44
 
53
- }
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
54
 
55
55
  }
56
56
 
@@ -1,2 +1,4 @@
1
1
  export { image } from './image'
2
2
  export { checkImage } from './check'
3
+ export { recycleImage } from './recycle'
4
+
@@ -5,64 +5,77 @@ import { IUI, ILeafPaint, IMatrixData } from '@leafer-ui/interface'
5
5
 
6
6
  const { get, scale: scaleHelper, copy } = MatrixHelper
7
7
 
8
- export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): void {
9
- const id = ui.__world.width + ui.__world.height
8
+ export function createPattern(ui: IUI, paint: ILeafPaint, pixelRatio: number): boolean {
10
9
 
11
- if (paint.patternId !== id) {
10
+ let { scaleX, scaleY } = ui.__world
11
+
12
+ const id = scaleX + scaleY
13
+
14
+ if (paint.patternId !== id && !ui.destroyed) {
12
15
 
13
16
  paint.patternId = id
14
17
 
15
- let scale: number, matrix: IMatrixData, { a, d } = ui.__world, { width, height, scaleX, scaleY, opacity, transform, mode } = paint.data
18
+ const { image, data } = paint
19
+ const maxWidth = image.isSVG ? 4096 : Math.min(image.width, 4096)
20
+ const maxHeight = image.isSVG ? 4096 : Math.min(image.height, 4096)
21
+ let scale: number, matrix: IMatrixData, { width, height, scaleX: sx, scaleY: sy, opacity, transform, mode } = data
16
22
 
17
- if (scaleX) {
23
+ if (sx) {
18
24
  matrix = get()
19
25
  copy(matrix, transform)
20
- scaleHelper(matrix, 1 / scaleX, 1 / scaleY)
21
- a *= scaleX
22
- d *= scaleY
26
+ scaleHelper(matrix, 1 / sx, 1 / sy)
27
+ scaleX *= sx
28
+ scaleY *= sy
23
29
  }
24
30
 
25
- a *= pixelRatio
26
- d *= pixelRatio
27
- width *= a
28
- height *= d
29
-
30
- const { image } = paint
31
- const maxWidth = image.isSVG ? 4096 : Math.min(image.width, 4096)
32
- const maxHeight = image.isSVG ? 4096 : Math.min(image.height, 4096)
31
+ scaleX *= pixelRatio
32
+ scaleY *= pixelRatio
33
+ width *= scaleX
34
+ height *= scaleY
33
35
 
34
36
  if (width > maxWidth || height > maxHeight) {
35
37
  scale = Math.max(width / maxWidth, height / maxHeight)
38
+ } else if (width < 32 || height < 32) {
39
+ scale = Math.min(width / 32, height / 32)
40
+ }
36
41
 
37
- a /= scale
38
- d /= scale
42
+ if (scale) {
43
+ scaleX /= scale
44
+ scaleY /= scale
39
45
  width /= scale
40
46
  height /= scale
41
47
  }
42
48
 
43
- if (scaleX) {
44
- a /= scaleX
45
- d /= scaleY
49
+ if (sx) {
50
+ scaleX /= sx
51
+ scaleY /= sy
46
52
  }
47
53
 
48
- if (transform || a !== 1 || d !== 1) {
54
+ if (transform || scaleX !== 1 || scaleY !== 1) {
49
55
  if (!matrix) {
50
56
  matrix = get()
51
57
  if (transform) copy(matrix, transform)
52
58
  }
53
- scaleHelper(matrix, 1 / a, 1 / d)
59
+ scaleHelper(matrix, 1 / scaleX, 1 / scaleY)
54
60
  }
55
61
 
56
- const style = Platform.canvas.createPattern(paint.image.getCanvas(width, height, opacity) as any, mode === 'repeat' ? 'repeat' : (Platform.origin.noRepeat || 'no-repeat'))
57
-
58
- paint.transform = null
62
+ const style = Platform.canvas.createPattern(image.getCanvas(width, height, opacity) as any, mode === 'repeat' ? 'repeat' : (Platform.origin.noRepeat || 'no-repeat'))
59
63
 
60
64
  try {
65
+ if (paint.transform) paint.transform = null
61
66
  if (matrix) style.setTransform ? style.setTransform(matrix) : paint.transform = matrix
62
67
  } catch (e) {
63
68
  paint.transform = matrix
64
69
  }
65
70
 
66
71
  paint.style = style
72
+
73
+ return true
74
+
75
+ } else {
76
+
77
+ return false
78
+
67
79
  }
80
+
68
81
  }
@@ -0,0 +1,41 @@
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
+ }