@leafer/path 1.0.0-alpha.21 → 1.0.0-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,37 +1,51 @@
1
1
  import { INumberMap, IStringMap } from '@leafer/interface'
2
2
 
3
+ export const CanvasCommandOnlyMap: INumberMap = {
4
+
5
+ N: 21, // rect
6
+ D: 22, // roundRect
7
+ X: 23, // simple roundRect
8
+ G: 24, // ellipse
9
+ F: 25, // simple ellipse
10
+ O: 26, // arc
11
+ P: 27, // simple arc
12
+ U: 28 // arcTo
13
+
14
+ }
3
15
 
4
16
  export const PathCommandMap: INumberMap = {
5
- M: 1, //moveto
17
+
18
+ // svg and canvas
19
+
20
+ M: 1, // moveto
6
21
  m: 10,
7
- L: 2, //lineto
22
+ L: 2, // lineto
8
23
  l: 20,
9
- H: 3, //horizontal lineto
24
+ H: 3, // horizontal lineto
10
25
  h: 30,
11
- V: 4, //vertical lineto
26
+ V: 4, // vertical lineto
12
27
  v: 40,
13
- C: 5, //curveto
28
+ C: 5, // curveto
14
29
  c: 50,
15
- S: 6, //smooth curveto
30
+ S: 6, // smooth curveto
16
31
  s: 60,
17
- Q: 7, //quadratic Belzier curve
32
+ Q: 7, // quadratic Belzier curve
18
33
  q: 70,
19
- T: 8, //smooth quadratic Belzier curveto
34
+ T: 8, // smooth quadratic Belzier curveto
20
35
  t: 80,
21
- A: 9, //elliptical Arc
36
+ A: 9, //e lliptical Arc
22
37
  a: 90,
23
- Z: 11, //closepath
38
+ Z: 11, // closepath
24
39
  z: 11,
25
40
 
26
- // 非svg标准的canvas绘图命令
27
- rect: 100,
28
- roundRect: 101,
29
- ellipse: 102,
30
- arc: 103,
31
- arcTo: 104
41
+ R: 12, // Catmull Rom
42
+
43
+ // canvas
44
+ ...CanvasCommandOnlyMap
32
45
  }
33
46
 
34
47
  export const PathCommandLengthMap: INumberMap = {
48
+
35
49
  M: 3, //moveto
36
50
  m: 3,
37
51
  L: 3, //lineto
@@ -53,15 +67,21 @@ export const PathCommandLengthMap: INumberMap = {
53
67
  Z: 1, //closepath
54
68
  z: 1,
55
69
 
56
- // 非svg标准的canvas绘图命令
57
- rect: 5,
58
- roundRect: 6,
59
- ellipse: 9,
60
- arc: 7,
61
- arcTo: 6
70
+ // canvas
71
+
72
+ N: 5, // rect
73
+ D: 9, // roundRect
74
+ X: 6, // simple roundRect
75
+ G: 9, // ellipse
76
+ F: 5, // simple ellipse
77
+ O: 7, // arc
78
+ P: 4, // simple arc
79
+ U: 6 // arcTo
80
+
62
81
  }
63
82
 
64
- export const PathCommandNeedConvertMap: INumberMap = { // convert to: M L C Q Z
83
+ export const NeedConvertToCanvasCommandMap: INumberMap = { // convert to: M L C Q Z
84
+
65
85
  // M: 1, //moveto
66
86
  m: 10,
67
87
  // L: 2, //lineto
@@ -83,25 +103,24 @@ export const PathCommandNeedConvertMap: INumberMap = { // convert to: M L C Q Z
83
103
  // Z: 11, //closepath
84
104
  // z: 11
85
105
 
86
- // 非svg标准的canvas绘图命令
87
- rect: 100,
88
- roundRect: 101,
89
- ellipse: 102,
90
- arc: 103,
91
- arcTo: 104
92
106
  }
93
107
 
94
108
 
109
+ export const NeedConvertToCurveCommandMap: INumberMap = {
110
+ ...NeedConvertToCanvasCommandMap,
111
+ ...CanvasCommandOnlyMap
112
+ }
113
+
95
114
  const P = PathCommandMap
96
115
 
97
- export const NumberPathCommandMap: IStringMap = {}
116
+ export const PathNumberCommandMap: IStringMap = {}
98
117
  for (let key in P) {
99
- NumberPathCommandMap[P[key]] = key
118
+ PathNumberCommandMap[P[key]] = key
100
119
  }
101
120
  // {1: 'M'}
102
121
 
103
- export const NumberPathCommandLengthMap: INumberMap = {}
122
+ export const PathNumberCommandLengthMap: INumberMap = {}
104
123
  for (let key in P) {
105
- NumberPathCommandLengthMap[P[key]] = PathCommandLengthMap[key]
124
+ PathNumberCommandLengthMap[P[key]] = PathCommandLengthMap[key]
106
125
  }
107
126
  // {1: 3}
@@ -1,8 +1,10 @@
1
- import { IPathCommandData } from '@leafer/interface'
1
+ import { IPathCommandData, IPointData } from '@leafer/interface'
2
2
  import { StringNumberMap } from '@leafer/math'
3
- import { PathCommandMap as Command, PathCommandNeedConvertMap as NeedConvertCommand, PathCommandLengthMap as CommandLength, NumberPathCommandMap as CommandName, NumberPathCommandLengthMap as NumberCommandLength } from './PathCommandMap'
3
+ import { Debug } from '@leafer/debug'
4
4
 
5
+ import { PathCommandMap as Command, NeedConvertToCanvasCommandMap, NeedConvertToCurveCommandMap, PathCommandLengthMap, PathNumberCommandMap, PathNumberCommandLengthMap } from './PathCommandMap'
5
6
  import { BezierHelper } from './BezierHelper'
7
+ import { EllipseHelper } from './EllipseHelper'
6
8
 
7
9
 
8
10
  interface ICurrentCommand {
@@ -12,8 +14,12 @@ interface ICurrentCommand {
12
14
  }
13
15
 
14
16
 
15
- const { M, m, L, l, H, h, V, v, C, c, S, s, Q, q, T, t, A, a, Z, z } = Command
16
- const { getFromACommand } = BezierHelper
17
+ const { M, m, L, l, H, h, V, v, C, c, S, s, Q, q, T, t, A, a, Z, z, N, D, X, G, F, O, P, U } = Command
18
+ const { rect, roundRect, arcTo, arc, ellipse, quadraticCurveTo } = BezierHelper
19
+ const { ellipticalArc } = EllipseHelper
20
+ const debug = Debug.get('PathConvert')
21
+
22
+ const setEndPoint = {} as IPointData
17
23
 
18
24
  export const PathConvert = {
19
25
 
@@ -23,11 +29,11 @@ export const PathConvert = {
23
29
  let i = 0, len = data.length, count: number, str: string = '', command: number, lastCommand: number
24
30
  while (i < len) {
25
31
  command = data[i]
26
- count = NumberCommandLength[command]
32
+ count = PathNumberCommandLengthMap[command]
27
33
  if (command === lastCommand) {
28
34
  str += ' ' // 重复的命令可以省略
29
35
  } else {
30
- str += CommandName[command]
36
+ str += PathNumberCommandMap[command]
31
37
  }
32
38
 
33
39
  for (let j = 1; j < count; j++) {
@@ -41,10 +47,11 @@ export const PathConvert = {
41
47
  return str
42
48
  },
43
49
 
44
- parse(pathString: string, convert: boolean = true): IPathCommandData {
50
+ parse(pathString: string, curveMode?: boolean): IPathCommandData {
45
51
 
46
- let needConvert: boolean, char: string, num = ''
52
+ let needConvert: boolean, char: string, lastChar: string, num = ''
47
53
  const data: IPathCommandData = []
54
+ const convertCommand = curveMode ? NeedConvertToCurveCommandMap : NeedConvertToCanvasCommandMap
48
55
 
49
56
  for (let i = 0, len = pathString.length; i < len; i++) {
50
57
 
@@ -59,32 +66,39 @@ export const PathConvert = {
59
66
  if (num) { pushData(data, Number(num)); num = '' }
60
67
 
61
68
  current.name = Command[char]
62
- current.length = CommandLength[char]
69
+ current.length = PathCommandLengthMap[char]
63
70
  current.index = 0
64
71
  pushData(data, current.name)
65
72
 
66
- if (!needConvert && NeedConvertCommand[char]) needConvert = true
73
+ if (!needConvert && convertCommand[char]) needConvert = true
67
74
 
68
75
  } else {
69
76
 
70
- if (char === '-') { // L-34-35
71
- if (num) { pushData(data, Number(num)) }
72
- num = char
77
+ if (char === '-' || char === '+') {
78
+
79
+ if (lastChar === 'e' || lastChar === 'E') { // L45e-12 21e+22
80
+ num += char
81
+ } else {
82
+ if (num) pushData(data, Number(num)) // L-34-35 L+12+28
83
+ num = char
84
+ }
85
+
73
86
  } else {
74
87
  if (num) { pushData(data, Number(num)); num = '' }
75
88
  }
76
89
 
77
90
  }
78
91
 
92
+ lastChar = char
93
+
79
94
  }
80
95
 
81
96
  if (num) pushData(data, Number(num))
82
97
 
83
- //console.log(pathString, P._data)
84
- return (convert && needConvert) ? PathConvert.convertToSimple(data) : data
98
+ return needConvert ? PathConvert.toCanvasData(data, curveMode) : data
85
99
  },
86
100
 
87
- convertToSimple(old: IPathCommandData): IPathCommandData {
101
+ toCanvasData(old: IPathCommandData, curveMode?: boolean): IPathCommandData {
88
102
 
89
103
  let x = 0, y = 0, x1 = 0, y1 = 0, i = 0, len = old.length, controlX: number, controlY: number, command: number, lastCommand: number, smooth: boolean
90
104
  const data: IPathCommandData = []
@@ -94,7 +108,7 @@ export const PathConvert = {
94
108
  command = old[i]
95
109
 
96
110
  switch (command) {
97
- //moveto x,y
111
+ //moveto(x, y)
98
112
  case m:
99
113
  old[i + 1] += x
100
114
  old[i + 2] += y
@@ -105,7 +119,7 @@ export const PathConvert = {
105
119
  i += 3
106
120
  break
107
121
 
108
- //horizontal lineto x
122
+ //horizontal lineto(x)
109
123
  case h:
110
124
  old[i + 1] += x
111
125
  case H:
@@ -114,7 +128,7 @@ export const PathConvert = {
114
128
  i += 2
115
129
  break
116
130
 
117
- //vertical lineto y
131
+ //vertical lineto(y)
118
132
  case v:
119
133
  old[i + 1] += y
120
134
  case V:
@@ -123,7 +137,7 @@ export const PathConvert = {
123
137
  i += 2
124
138
  break
125
139
 
126
- //lineto x,y
140
+ //lineto(x,y)
127
141
  case l:
128
142
  old[i + 1] += x
129
143
  old[i + 2] += y
@@ -134,7 +148,7 @@ export const PathConvert = {
134
148
  i += 3
135
149
  break
136
150
 
137
- //smooth bezierCurveTo x2,y2,x,y
151
+ //smooth bezierCurveTo(x2, y2, x, y)
138
152
  case s: //smooth
139
153
  old[i + 1] += x
140
154
  old[i + 2] += y
@@ -153,7 +167,7 @@ export const PathConvert = {
153
167
  i += 5
154
168
  break
155
169
 
156
- //bezierCurveTo x1,y1,x2,y2,x,y
170
+ //bezierCurveTo(x1, y1, x2, y2, x, y)
157
171
  case c:
158
172
  old[i + 1] += x
159
173
  old[i + 2] += y
@@ -171,7 +185,7 @@ export const PathConvert = {
171
185
  i += 7
172
186
  break
173
187
 
174
- //smooth quadraticCurveTo x,y
188
+ //smooth quadraticCurveTo(x, y)
175
189
  case t:
176
190
  old[i + 1] += x
177
191
  old[i + 2] += y
@@ -180,13 +194,13 @@ export const PathConvert = {
180
194
  smooth = (lastCommand === Q) || (lastCommand === T)
181
195
  controlX = smooth ? (x * 2 - controlX) : old[i + 1]
182
196
  controlY = smooth ? (y * 2 - controlY) : old[i + 2]
197
+ curveMode ? quadraticCurveTo(data, x, y, controlX, controlY, old[i + 1], old[i + 2]) : data.push(Q, controlX, controlY, old[i + 1], old[i + 2])
183
198
  x = old[i + 1]
184
199
  y = old[i + 2]
185
- data.push(Q, controlX, controlY, x, y)
186
200
  i += 3
187
201
  break
188
202
 
189
- //quadraticCurveTo x1,y1,x,y
203
+ //quadraticCurveTo(x1, y1, x, y)
190
204
  case q:
191
205
  old[i + 1] += x
192
206
  old[i + 2] += y
@@ -196,18 +210,18 @@ export const PathConvert = {
196
210
  case Q:
197
211
  controlX = old[i + 1]
198
212
  controlY = old[i + 2]
213
+ curveMode ? quadraticCurveTo(data, x, y, controlX, controlY, old[i + 3], old[i + 4]) : data.push(Q, controlX, controlY, old[i + 3], old[i + 4])
199
214
  x = old[i + 3]
200
215
  y = old[i + 4]
201
- data.push(Q, controlX, controlY, x, y)
202
216
  i += 5
203
217
  break
204
218
 
205
- //ellipticalArc rx ry x-axis-rotation large-arc-flag sweep-flag x y
219
+ //ellipticalArc(rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y)
206
220
  case a:
207
221
  old[i + 6] += x
208
222
  old[i + 7] += y
209
223
  case A:
210
- data.push(...getFromACommand(x, y, old[i + 1], old[i + 2], old[i + 3], old[i + 4], old[i + 5], old[i + 6], old[i + 7])) // convert bezier
224
+ ellipticalArc(data, x, y, old[i + 1], old[i + 2], old[i + 3], old[i + 4], old[i + 5], old[i + 6], old[i + 7], curveMode) // convert to canvas ellipse or curve
211
225
  x = old[i + 6]
212
226
  y = old[i + 7]
213
227
  i += 8
@@ -217,6 +231,61 @@ export const PathConvert = {
217
231
  data.push(Z)
218
232
  i++
219
233
  break
234
+
235
+
236
+ // canvas command
237
+
238
+ case N: // rect(x, y, width, height)
239
+ x = old[i + 1]
240
+ y = old[i + 2]
241
+ curveMode ? rect(data, x, y, old[i + 3], old[i + 4]) : copyData(data, old, i, 5)
242
+ i += 5
243
+ break
244
+ case D: // roundRect(x, y, width, height, radius1, radius2, radius3, radius4)
245
+ x = old[i + 1]
246
+ y = old[i + 2]
247
+ curveMode ? roundRect(data, x, y, old[i + 3], old[i + 4], [old[i + 5], old[i + 6], old[i + 7], old[i + 8]]) : copyData(data, old, i, 9)
248
+ i += 9
249
+ break
250
+ case X: // simple roundRect(x, y, width, height, radius)
251
+ x = old[i + 1]
252
+ y = old[i + 2]
253
+ curveMode ? roundRect(data, x, y, old[i + 3], old[i + 4], old[i + 5]) : copyData(data, old, i, 6)
254
+ i += 6
255
+ break
256
+ case G: // ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
257
+ ellipse(curveMode ? data : copyData(data, old, i, 9), old[i + 1], old[i + 2], old[i + 3], old[i + 4], old[i + 5], old[i + 6], old[i + 7], old[i + 8] as unknown as boolean, null, setEndPoint)
258
+ x = setEndPoint.x
259
+ y = setEndPoint.y
260
+ i += 9
261
+ break
262
+ case F: // simple ellipse(x, y, radiusX, radiusY)
263
+ curveMode ? ellipse(data, old[i + 1], old[i + 2], old[i + 3], old[i + 4], 0, 0, 360, false) : copyData(data, old, i, 5)
264
+ x = old[i + 1] + old[i + 3]
265
+ y = old[i + 2]
266
+ i += 5
267
+ break
268
+ case O: // arc(x, y, radius, startAngle, endAngle, anticlockwise)
269
+ arc(curveMode ? data : copyData(data, old, i, 7), old[i + 1], old[i + 2], old[i + 3], old[i + 4], old[i + 5], old[i + 6] as unknown as boolean, null, setEndPoint)
270
+ x = setEndPoint.x
271
+ y = setEndPoint.y
272
+ i += 7
273
+ break
274
+ case P: // simple arc(x, y, radius)
275
+ curveMode ? arc(data, old[i + 1], old[i + 2], old[i + 3], 0, 360, false) : copyData(data, old, i, 4)
276
+ x = old[i + 1] + old[i + 3]
277
+ y = old[i + 2]
278
+ i += 4
279
+ break
280
+ case U: // arcTo(x1, y1, x2, y2, radius)
281
+ arcTo(curveMode ? data : copyData(data, old, i, 6), x, y, old[i + 1], old[i + 2], old[i + 3], old[i + 4], old[i + 5], null, setEndPoint)
282
+ x = setEndPoint.x
283
+ y = setEndPoint.y
284
+ i += 6
285
+ break
286
+ default:
287
+ debug.error(`command: ${command} [index:${i}]`, old)
288
+ return data
220
289
  }
221
290
 
222
291
  lastCommand = command
@@ -226,6 +295,12 @@ export const PathConvert = {
226
295
 
227
296
  },
228
297
 
298
+ copyData(data: IPathCommandData, old: IPathCommandData, index: number, count: number): void {
299
+ for (let i = index, end = index + count; i < end; i++) {
300
+ data.push(old[i])
301
+ }
302
+ },
303
+
229
304
  pushData(data: IPathCommandData, num: number) {
230
305
  if (current.index === current.length) { // 单个命令,多个数据的情况
231
306
  current.index = 1
@@ -238,4 +313,4 @@ export const PathConvert = {
238
313
 
239
314
  }
240
315
 
241
- const { current, pushData } = PathConvert
316
+ const { current, pushData, copyData } = PathConvert
@@ -0,0 +1,10 @@
1
+ import { IPathCommandData } from '@leafer/interface'
2
+
3
+
4
+ export const PathCorner = {
5
+
6
+ smooth(data: IPathCommandData, _cornerRadius: number, _cornerSmoothing?: number): IPathCommandData {
7
+ return data
8
+ }
9
+
10
+ }
@@ -1,64 +1,92 @@
1
- import { IPathCommandData } from '@leafer/interface'
2
- import { PathCommandMap } from './PathCommandMap'
1
+ import { IPathCommandData, IPathDrawer } from '@leafer/interface'
2
+ import { PathCommandDataHelper } from './PathCommandDataHelper'
3
+ import { IPathString } from '@leafer-ui/interface'
4
+ import { PathHelper } from './PathHelper'
3
5
 
4
6
 
5
- let data: IPathCommandData
6
- const { M, L, C, Q, Z, rect, roundRect, ellipse, arc, arcTo } = PathCommandMap
7
+ const { moveTo, lineTo, quadraticCurveTo, bezierCurveTo, closePath, beginPath, rect, roundRect, ellipse, arc, arcTo, moveToEllipse, moveToArc } = PathCommandDataHelper
7
8
 
8
- export const PathCreator = {
9
+ export class PathCreator implements IPathDrawer {
9
10
 
10
- begin(commandData: IPathCommandData): void {
11
- data = commandData
12
- },
11
+ public path: IPathCommandData
13
12
 
14
- end(): void {
15
- data = null
16
- },
13
+ constructor(path?: IPathCommandData | IPathString) {
14
+ if (path) {
15
+ this.path = typeof path === 'string' ? PathHelper.parse(path) : path
16
+ } else {
17
+ this.path = []
18
+ }
19
+ }
20
+
21
+ public beginPath(): PathCreator {
22
+ beginPath(this.path)
23
+ return this
24
+ }
25
+
26
+ // svg and canvas
17
27
 
18
- // draw
28
+ public moveTo(x: number, y: number): PathCreator {
29
+ moveTo(this.path, x, y)
30
+ return this
31
+ }
32
+
33
+ public lineTo(x: number, y: number): PathCreator {
34
+ lineTo(this.path, x, y)
35
+ return this
36
+ }
19
37
 
20
- moveTo(x: number, y: number): void {
21
- data.push(M, x, y)
22
- },
38
+ public bezierCurveTo(x1: number, y1: number, x2: number, y2: number, x: number, y: number): PathCreator {
39
+ bezierCurveTo(this.path, x1, y1, x2, y2, x, y)
40
+ return this
41
+ }
23
42
 
24
- lineTo(x: number, y: number): void {
25
- data.push(L, x, y)
26
- },
43
+ public quadraticCurveTo(x1: number, y1: number, x: number, y: number): PathCreator {
44
+ quadraticCurveTo(this.path, x1, y1, x, y)
45
+ return this
46
+ }
27
47
 
28
- bezierCurveTo(x1: number, y1: number, x2: number, y2: number, x: number, y: number): void {
29
- data.push(C, x1, y1, x2, y2, x, y)
30
- },
48
+ public closePath(): PathCreator {
49
+ closePath(this.path)
50
+ return this
51
+ }
31
52
 
32
- quadraticCurveTo(x1: number, y1: number, x: number, y: number): void {
33
- data.push(Q, x1, y1, x, y)
34
- },
53
+ // canvas
35
54
 
36
- close(end?: boolean): void {
37
- data.push(Z)
38
- if (end) data = null
39
- },
55
+ public rect(x: number, y: number, width: number, height: number): PathCreator {
56
+ rect(this.path, x, y, width, height)
57
+ return this
58
+ }
40
59
 
60
+ public roundRect(x: number, y: number, width: number, height: number, cornerRadius: number | number[]): PathCreator {
61
+ roundRect(this.path, x, y, width, height, cornerRadius)
62
+ return this
63
+ }
41
64
 
42
- // 非svg标准的canvas绘图命令
65
+ public ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation?: number, startAngle?: number, endAngle?: number, anticlockwise?: boolean): PathCreator {
66
+ ellipse(this.path, x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
67
+ return this
68
+ }
43
69
 
44
- rect(x: number, y: number, width: number, height: number): void {
45
- data.push(rect, x, y, width, height)
46
- },
70
+ public arc(x: number, y: number, radius: number, startAngle?: number, endAngle?: number, anticlockwise?: boolean): PathCreator {
71
+ arc(this.path, x, y, radius, startAngle, endAngle, anticlockwise)
72
+ return this
73
+ }
47
74
 
48
- roundRect(x: number, y: number, width: number, height: number, cornerRadius?: number | number[]): void {
49
- data.push(roundRect, x, y, width, height, cornerRadius as unknown as number)
50
- },
75
+ public arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): PathCreator {
76
+ arcTo(this.path, x1, y1, x2, y2, radius)
77
+ return this
78
+ }
51
79
 
52
- ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {
53
- data.push(ellipse, x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise as unknown as number)
54
- },
80
+ // moveTo, then draw
55
81
 
56
- arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {
57
- data.push(arc, x, y, radius, startAngle, endAngle, counterclockwise as unknown as number)
58
- },
82
+ public moveToEllipse(x: number, y: number, radiusX: number, radiusY: number, rotation?: number, startAngle?: number, endAngle?: number, anticlockwise?: boolean): PathCreator {
83
+ moveToEllipse(this.path, x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
84
+ return this
85
+ }
59
86
 
60
- arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void {
61
- data.push(arcTo, x1, y1, x2, y2, radius)
87
+ public moveToArc(x: number, y: number, radius: number, startAngle?: number, endAngle?: number, anticlockwise?: boolean): PathCreator {
88
+ moveToArc(this.path, x, y, radius, startAngle, endAngle, anticlockwise)
89
+ return this
62
90
  }
63
91
 
64
92
  }
@@ -0,0 +1,85 @@
1
+ import { IPathDrawer, IPathCommandData } from '@leafer/interface'
2
+ import { OneRadian, PI2 } from '@leafer/math'
3
+ import { Debug } from '@leafer/debug'
4
+
5
+ import { PathCommandMap as Command } from './PathCommandMap'
6
+
7
+
8
+ const { M, L, C, Q, Z, N, D, X, G, F, O, P, U } = Command
9
+ const debug = Debug.get('PathDrawer')
10
+
11
+ export const PathDrawer = {
12
+
13
+ drawPathByData(drawer: IPathDrawer, data: IPathCommandData): void {
14
+ if (!data) return
15
+
16
+ let command: number
17
+ let i = 0, len = data.length
18
+
19
+ while (i < len) {
20
+ command = data[i]
21
+ switch (command) {
22
+ case M: //moveto(x, y)
23
+ drawer.moveTo(data[i + 1], data[i + 2])
24
+ i += 3
25
+ break
26
+ case L: //lineto(x, y)
27
+ drawer.lineTo(data[i + 1], data[i + 2])
28
+ i += 3
29
+ break
30
+ case C: //bezierCurveTo(x1, y1, x2, y2, x, y)
31
+ drawer.bezierCurveTo(data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5], data[i + 6])
32
+ i += 7
33
+ break
34
+ case Q: //quadraticCurveTo(x1, y1, x, y)
35
+ drawer.quadraticCurveTo(data[i + 1], data[i + 2], data[i + 3], data[i + 4])
36
+ i += 5
37
+ break
38
+ case Z: //closepath()
39
+ drawer.closePath()
40
+ i += 1
41
+ break
42
+
43
+ // canvas command
44
+
45
+ case N: // rect(x, y, width, height)
46
+ drawer.rect(data[i + 1], data[i + 2], data[i + 3], data[i + 4])
47
+ i += 5
48
+ break
49
+ case D: // roundRect(x, y, width, height, radius1, radius2, radius3, radius4)
50
+ drawer.roundRect(data[i + 1], data[i + 2], data[i + 3], data[i + 4], [data[i + 5], data[i + 6], data[i + 7], data[i + 8]])
51
+ i += 9
52
+ break
53
+ case X: // simple roundRect(x, y, width, height, radius)
54
+ drawer.roundRect(data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5])
55
+ i += 6
56
+ break
57
+ case G: // ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
58
+ drawer.ellipse(data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5] * OneRadian, data[i + 6] * OneRadian, data[i + 7] * OneRadian, data[i + 8] as unknown as boolean)
59
+ i += 9
60
+ break
61
+ case F: // simple ellipse(x, y, radiusX, radiusY)
62
+ drawer.ellipse(data[i + 1], data[i + 2], data[i + 3], data[i + 4], 0, 0, PI2, false)
63
+ i += 5
64
+ break
65
+ case O: // arc(x, y, radius, startAngle, endAngle, anticlockwise)
66
+ drawer.arc(data[i + 1], data[i + 2], data[i + 3], data[i + 4] * OneRadian, data[i + 5] * OneRadian, data[i + 6] as unknown as boolean)
67
+ i += 7
68
+ break
69
+ case P: // simple arc(x, y, radius)
70
+ drawer.arc(data[i + 1], data[i + 2], data[i + 3], 0, PI2, false)
71
+ i += 4
72
+ break
73
+ case U: // arcTo(x1, y1, x2, y2, radius)
74
+ drawer.arcTo(data[i + 1], data[i + 2], data[i + 3], data[i + 4], data[i + 5])
75
+ i += 6
76
+ break
77
+ default:
78
+ debug.error(`command: ${command} [index:${i}]`, data)
79
+ return
80
+ }
81
+ }
82
+
83
+ }
84
+
85
+ }