@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer-ui/paint",
3
- "version": "1.0.0-alpha.23",
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",
23
- "@leafer-ui/interface": "1.0.0-alpha.23"
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 { stringColor } from '@leafer-ui/color'
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
- const paint: IPaint[] = ui.__.__input[attrName] as IPaint[]
20
- if (typeof paint === 'object') {
21
- let item: ILeafPaint
22
- const value: ILeafPaint[] = []
23
- for (let i = 0, len = paint.length; i < len; i++) {
24
- item = getLeafPaint(ui, paint[i], attrName)
25
- if (item) value.push(item)
26
- }
27
- ui.__['_' + attrName] = value.length ? value : undefined
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: stringColor(color) }
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, width, height)
41
+ return image(ui, attrName, paint, boxBounds)
41
42
  case 'linear':
42
- return linearGradient(paint, width, height)
43
+ return linearGradient(paint, boxBounds)
43
44
  case 'radial':
44
- return radialGradient(paint, width, height)
45
+ return radialGradient(paint, boxBounds)
45
46
  case 'angular':
46
- return conicGradient(paint, width, height)
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
- canvas.fill(windingRule)
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
- canvas.fill(windingRule)
33
+
34
+ __font ? drawText(ui, canvas) : canvas.fill(windingRule)
35
+
33
36
  canvas.restoreBlendMode()
34
37
  } else {
35
- canvas.fill(windingRule)
38
+
39
+ __font ? drawText(ui, canvas) : canvas.fill(windingRule)
40
+
36
41
  }
37
42
  }
38
43
  }
@@ -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 { renderBoundsSpreadWidth } = ui.__layout
19
- const worldClipBounds = BoundsHelper.getIntersectData(renderBoundsSpreadWidth ? BoundsHelper.getSpread(current.bounds, renderBoundsSpreadWidth * __world.a) : current.bounds, __world, options.matrix)
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 = BoundsHelper.getOuterOf(__world, matrix)
31
- bounds = BoundsHelper.getByMove(shapeBounds, -matrix.e, -matrix.f)
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
- switch (strokeAlign) {
11
+ if (__font) {
11
12
 
12
- case 'center':
13
- canvas.setStroke(undefined, strokeWidth, options)
14
- canvas.strokeStyle = stroke
15
- canvas.stroke()
16
- break
13
+ strokeText(ui, canvas, stroke)
17
14
 
18
- case 'inside':
19
- canvas.save()
20
- canvas.setStroke(undefined, strokeWidth * 2, options)
21
- canvas.clip(options.windingRule)
15
+ } else {
22
16
 
23
- canvas.strokeStyle = stroke
24
- canvas.stroke()
17
+ switch (strokeAlign) {
25
18
 
26
- canvas.restore()
27
- break
19
+ case 'center':
28
20
 
29
- case 'outside':
30
- const out = canvas.getSameCanvas(true)
31
- ui.__drawRenderPath(out)
21
+ canvas.setStroke(stroke, strokeWidth, options)
22
+ canvas.stroke()
23
+ break
32
24
 
33
- out.setStroke(undefined, strokeWidth * 2, ui.__)
25
+ case 'inside':
34
26
 
35
- out.strokeStyle = stroke
36
- out.stroke()
27
+ canvas.save()
28
+ canvas.setStroke(stroke, strokeWidth * 2, options)
37
29
 
38
- out.clip(options.windingRule)
39
- out.clearWorld(ui.__layout.renderBounds)
30
+ canvas.clip(options.windingRule)
31
+ canvas.stroke()
40
32
 
41
- canvas.copyWorldToInner(out, ui.__world, ui.__layout.renderBounds)
42
- out.recycle()
43
- break
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
- switch (strokeAlign) {
67
+ switch (strokeAlign) {
53
68
 
54
- case 'center':
55
- canvas.setStroke(undefined, strokeWidth, options)
56
- drawStrokesStyle(strokes, canvas)
57
- break
69
+ case 'center':
70
+ canvas.setStroke(undefined, strokeWidth, options)
71
+ drawStrokesStyle(strokes, canvas)
72
+ break
58
73
 
59
- case 'inside':
60
- canvas.save()
61
- canvas.setStroke(undefined, strokeWidth * 2, options)
62
- canvas.clip(options.windingRule)
74
+ case 'inside':
75
+ canvas.save()
76
+ canvas.setStroke(undefined, strokeWidth * 2, options)
77
+ canvas.clip(options.windingRule)
63
78
 
64
- drawStrokesStyle(strokes, canvas)
79
+ drawStrokesStyle(strokes, canvas)
65
80
 
66
- canvas.restore()
67
- break
81
+ canvas.restore()
82
+ break
68
83
 
69
- case 'outside':
70
- const { renderBounds } = ui.__layout
71
- const out = canvas.getSameCanvas(true)
72
- ui.__drawRenderPath(out)
84
+ case 'outside':
85
+ const { renderBounds } = ui.__layout
86
+ const out = canvas.getSameCanvas(true)
87
+ ui.__drawRenderPath(out)
73
88
 
74
- out.setStroke(undefined, strokeWidth * 2, ui.__)
89
+ out.setStroke(undefined, strokeWidth * 2, ui.__)
75
90
 
76
- drawStrokesStyle(strokes, out)
91
+ drawStrokesStyle(strokes, out)
77
92
 
78
- out.clip(options.windingRule)
79
- out.clearWorld(renderBounds)
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'
@@ -1,9 +1,10 @@
1
- import { IGradientPaint, ILeafPaint, IMatrixData, IPointData } from '@leafer-ui/interface'
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, width: number, height: number): ILeafPaint {
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
- set(realFrom, from.x * width, from.y * height)
23
- set(realTo, to.x * width, to.y * height)
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 {
@@ -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, boxWidth: number, boxHeight: number): ILeafPaint {
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 = boxWidth === width && boxHeight === height
23
+ const sameBox = box.width === width && box.height === height
23
24
 
24
25
  switch (mode) {
25
26
  case 'strench':
26
- if (!sameBox) width = boxWidth, height = boxHeight
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 = getCropTransform(offset, scale, rotation)
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, boxWidth, boxHeight, rotation)
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.__updateAttr('width')
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 getCropTransform(offset: IPointData, scale: number | IPointData, rotation: number): IMatrixData {
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 = boxWidth / (swap ? imageHeight : imageWidth)
70
- const sh = boxHeight / (swap ? imageWidth : imageHeight)
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 = (boxWidth - imageWidth * scale) / 2
73
- const y = (boxHeight - imageHeight * scale) / 2
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(imageWidth: number, imageHeight: number, scale: number, rotation: number): IMatrixData {
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, imageHeight, 0)
93
+ translate(transform, height, 0)
91
94
  break
92
95
  case 180:
93
- translate(transform, imageWidth, imageHeight)
96
+ translate(transform, width, height)
94
97
  break
95
98
  case 270:
96
- translate(transform, 0, imageWidth)
99
+ translate(transform, 0, width)
97
100
  break
98
101
  }
99
102
  }
100
- if (scale) scaleOf(transform, { x: 0, y: 0 }, scale)
103
+ translate(transform, box.x, box.y)
104
+ if (scale) scaleOf(transform, box, scale)
101
105
  return transform
102
106
  }
103
107
 
@@ -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 { stringColor } from '@leafer-ui/color'
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, width: number, height: number): ILeafPaint {
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, stringColor(stop.color, opacity))
33
+ gradient.addColorStop(stop.offset, ColorConvert.string(stop.color, opacity))
34
34
  }
35
35
  }
@@ -1,5 +1,8 @@
1
- import { IGradientPaint, ILeafPaint, IMatrixData, IPointData } from '@leafer-ui/interface'
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, width: number, height: number): ILeafPaint {
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
- set(realFrom, from.x * width, from.y * height)
23
- set(realTo, to.x * width, to.y * height)
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)