@syncfusion/ej2-image-editor 31.1.17 → 31.1.22

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.
Files changed (55) hide show
  1. package/dist/ej2-image-editor.umd.min.js +3 -3
  2. package/dist/ej2-image-editor.umd.min.js.map +1 -1
  3. package/dist/es6/ej2-image-editor.es2015.js +72 -9
  4. package/dist/es6/ej2-image-editor.es2015.js.map +1 -1
  5. package/dist/es6/ej2-image-editor.es5.js +72 -9
  6. package/dist/es6/ej2-image-editor.es5.js.map +1 -1
  7. package/dist/global/ej2-image-editor.min.js +3 -3
  8. package/dist/global/ej2-image-editor.min.js.map +1 -1
  9. package/dist/global/index.d.ts +2 -2
  10. package/package.json +14 -46
  11. package/src/image-editor/action/export.js +6 -2
  12. package/src/image-editor/action/freehand-draw.d.ts +1 -0
  13. package/src/image-editor/action/freehand-draw.js +30 -3
  14. package/src/image-editor/action/selection.js +14 -2
  15. package/src/image-editor/action/undo-redo.js +10 -0
  16. package/src/image-editor/base/image-editor.d.ts +1 -0
  17. package/src/image-editor/base/image-editor.js +9 -2
  18. package/src/image-editor/renderer/toolbar.js +3 -0
  19. package/dist/ts/image-editor/action/crop.d.ts +0 -44
  20. package/dist/ts/image-editor/action/crop.ts +0 -867
  21. package/dist/ts/image-editor/action/draw.d.ts +0 -187
  22. package/dist/ts/image-editor/action/draw.ts +0 -4924
  23. package/dist/ts/image-editor/action/export.d.ts +0 -29
  24. package/dist/ts/image-editor/action/export.ts +0 -509
  25. package/dist/ts/image-editor/action/filter.d.ts +0 -48
  26. package/dist/ts/image-editor/action/filter.ts +0 -872
  27. package/dist/ts/image-editor/action/freehand-draw.d.ts +0 -68
  28. package/dist/ts/image-editor/action/freehand-draw.ts +0 -1135
  29. package/dist/ts/image-editor/action/index.d.ts +0 -9
  30. package/dist/ts/image-editor/action/index.ts +0 -9
  31. package/dist/ts/image-editor/action/selection.d.ts +0 -178
  32. package/dist/ts/image-editor/action/selection.ts +0 -5241
  33. package/dist/ts/image-editor/action/shape.d.ts +0 -130
  34. package/dist/ts/image-editor/action/shape.ts +0 -3917
  35. package/dist/ts/image-editor/action/transform.d.ts +0 -77
  36. package/dist/ts/image-editor/action/transform.ts +0 -2008
  37. package/dist/ts/image-editor/action/undo-redo.d.ts +0 -52
  38. package/dist/ts/image-editor/action/undo-redo.ts +0 -1169
  39. package/dist/ts/image-editor/base/enum.d.ts +0 -277
  40. package/dist/ts/image-editor/base/enum.ts +0 -288
  41. package/dist/ts/image-editor/base/image-editor-model.d.ts +0 -770
  42. package/dist/ts/image-editor/base/image-editor.d.ts +0 -1928
  43. package/dist/ts/image-editor/base/image-editor.ts +0 -5496
  44. package/dist/ts/image-editor/base/index.d.ts +0 -4
  45. package/dist/ts/image-editor/base/index.ts +0 -4
  46. package/dist/ts/image-editor/base/interface.d.ts +0 -1637
  47. package/dist/ts/image-editor/base/interface.ts +0 -1709
  48. package/dist/ts/image-editor/index.d.ts +0 -3
  49. package/dist/ts/image-editor/index.ts +0 -3
  50. package/dist/ts/image-editor/renderer/index.d.ts +0 -1
  51. package/dist/ts/image-editor/renderer/index.ts +0 -1
  52. package/dist/ts/image-editor/renderer/toolbar.d.ts +0 -171
  53. package/dist/ts/image-editor/renderer/toolbar.ts +0 -6356
  54. package/dist/ts/index.d.ts +0 -4
  55. package/dist/ts/index.ts +0 -4
@@ -1,3917 +0,0 @@
1
- /* eslint-disable no-constant-condition */
2
- import { EventHandler, extend, isNullOrUndefined } from '@syncfusion/ej2-base';
3
- import { CurrentObject, ImageEditor, Point, SelectionPoint, CropSelectionSettings, ShapeChangeEventArgs, ShapeSettings, ShapeType,
4
- StrokeSettings, TextSettings, RedactType, RedactSettings, ArrowheadType, ActivePoint, TransformationCollection} from '../index';
5
-
6
- export class Shape {
7
- private parent: ImageEditor;
8
- private lowerContext: CanvasRenderingContext2D;
9
- private upperContext: CanvasRenderingContext2D;
10
- private textSettings: TextSettings =
11
- {text: 'Enter Text', fontFamily: '', fontSize: null, fontRatio: null, bold: false, italic: false, underline: false, strikethrough: false};
12
- private strokeSettings: StrokeSettings = {strokeColor: '#fff', fillColor: '', strokeWidth: null, radius: null, outlineColor: '', outlineWidth: null};
13
- private keyHistory: string = ''; // text history
14
- private prevObj: CurrentObject;
15
- private shapeImg: HTMLImageElement;
16
- private preventFrameAnnotation: boolean = false;
17
- private redactType: string = 'blur';
18
-
19
- constructor(parent: ImageEditor) {
20
- this.parent = parent;
21
- this.addEventListener();
22
- }
23
-
24
- public destroy(): void {
25
- if (this.parent.isDestroyed) { return; }
26
- this.removeEventListener();
27
- }
28
-
29
- private addEventListener(): void {
30
- this.parent.on('shape', this.shape, this);
31
- this.parent.on('destroyed', this.destroy, this);
32
- }
33
-
34
- private removeEventListener(): void {
35
- this.parent.off('shape', this.shape);
36
- this.parent.off('destroyed', this.destroy);
37
- }
38
-
39
- private shape(args?: { onPropertyChange: boolean, prop: string, value?: object }): void {
40
- const parent: ImageEditor = this.parent;
41
- this.initShapePvtProps(); let uploader: HTMLElement;
42
- switch (args.prop) {
43
- case 'drawEllipse':
44
- this.drawEllipse(args.value['x'], args.value['y'], args.value['radiusX'], args.value['radiusY'],
45
- args.value['strokeWidth'], args.value['strokeColor'], args.value['fillColor'],
46
- args.value['degree'], args.value['isSelected']);
47
- break;
48
- case 'drawLine':
49
- this.drawLine(args.value['startX'], args.value['startY'], args.value['endX'], args.value['endY'],
50
- args.value['strokeWidth'], args.value['strokeColor'], args.value['isSelected']);
51
- break;
52
- case 'drawArrow':
53
- this.drawArrow(args.value['startX'], args.value['startY'], args.value['endX'], args.value['endY'],
54
- args.value['strokeWidth'], args.value['strokeColor'], args.value['arrowStart'],
55
- args.value['arrowEnd'], args.value['isSelected']);
56
- break;
57
- case 'drawPath':
58
- this.drawPath(args.value['pointColl'], args.value['strokeWidth'], args.value['strokeColor'], args.value['isSelected']);
59
- break;
60
- case 'drawRectangle':
61
- this.drawRectangle(args.value['x'], args.value['y'], args.value['width'], args.value['height'],
62
- args.value['strokeWidth'], args.value['strokeColor'], args.value['fillColor'],
63
- args.value['degree'], args.value['isSelected'], args.value['radius']);
64
- break;
65
- case 'drawText':
66
- this.drawText(args.value['x'], args.value['y'], args.value['text'], args.value['fontFamily'],
67
- args.value['fontSize'], args.value['bold'], args.value['italic'], args.value['color'],
68
- args.value['isSelected'], args.value['degree'], args.value['fillColor'], args.value['outlineColor'],
69
- args.value['outlineWidth'], args.value['transformCollection'], args.value['underline'], args.value['strikethrough']);
70
- break;
71
- case 'redrawActObj':
72
- this.redrawActObj(args.value['x'], args.value['y'], args.value['isMouseDown']);
73
- break;
74
- case 'apply':
75
- this.apply(args.value['shape'], args.value['obj'], args.value['canvas']);
76
- break;
77
- case 'updateShapeChangeEventArgs':
78
- this.updateShapeChangeEventArgs(args.value['shapeSettings'], args.value['allowShapeOverflow']);
79
- break;
80
- case 'updSelChangeEventArgs':
81
- this.updSelChangeEventArgs(args.value['selectionSettings']);
82
- break;
83
- case 'iterateObjColl':
84
- this.iterateObjColl();
85
- break;
86
- case 'updImgRatioForActObj':
87
- this.updImgRatioForActObj();
88
- break;
89
- case 'redrawObj':
90
- this.redrawObj(args.value['degree']);
91
- break;
92
- case 'redraw-text':
93
- this.redrawText();
94
- break;
95
- case 'draw-shape':
96
- this.drawShape(args.value['obj'] as string, args.value['strokeWidth'], args.value['strokeColor'],
97
- args.value['fillColor'], args.value['start'], args.value['width'], args.value['height']);
98
- break;
99
- case 'renderTextArea':
100
- this.renderTextArea(args.value['x'], args.value['y'], args.value['actObj']);
101
- break;
102
- case 'setTextBoxWidth':
103
- this.setTextBoxWidth(args.value['e']);
104
- break;
105
- case 'findTextTarget':
106
- this.findTextTarget(args.value['e']);
107
- break;
108
- case 'updateFontStyles':
109
- this.updateFontStyles(args.value['isTextBox']);
110
- break;
111
- case 'applyFontStyle':
112
- this.applyFontStyle(args.value['item']);
113
- break;
114
- case 'updateFontRatio':
115
- this.updateFontRatio(args.value['obj'], args.value['isTextArea']);
116
- break;
117
- case 'updateFontSize':
118
- this.updateFontSize(args.value['obj']);
119
- break;
120
- case 'pushActItemIntoObj':
121
- this.pushActItemIntoObj();
122
- break;
123
- case 'clearActObj':
124
- this.clearActObj();
125
- break;
126
- case 'refreshActiveObj':
127
- this.refreshActiveObj();
128
- break;
129
- case 'applyActObj':
130
- this.applyActObj(args.value['isMouseDown']);
131
- break;
132
- case 'wireEvent':
133
- EventHandler.add(parent.upperCanvas, 'dblclick', this.findTextTarget, this);
134
- EventHandler.add(parent.textArea, 'mousedown', this.findTextTarget, this);
135
- uploader = document.getElementById(parent.element.id + '_fileUpload');
136
- if (uploader) {
137
- EventHandler.add(uploader, 'change', this.fileChanged, this);
138
- }
139
- break;
140
- case 'unWireEvent':
141
- EventHandler.remove(parent.upperCanvas, 'dblclick', this.findTextTarget);
142
- EventHandler.remove(parent.textArea, 'mousedown', this.findTextTarget);
143
- uploader = document.getElementById(parent.element.id + '_fileUpload');
144
- if (uploader) {
145
- EventHandler.remove(uploader, 'change', this.fileChanged);
146
- }
147
- break;
148
- case 'getShapeSetting':
149
- this.getShapeSetting(args.value['id'], args.value['obj']);
150
- break;
151
- case 'getShapeSettings':
152
- this.getShapeSettings(args.value['obj']);
153
- break;
154
- case 'getRedactSettings':
155
- this.getRedactSettings(args.value['obj']);
156
- break;
157
- case 'isPointsInRange':
158
- this.isPointsInRange(args.value['x'], args.value['y'], args.value['obj']);
159
- break;
160
- case 'alignRotateFlipColl':
161
- this.alignRotateFlipColl(args.value['collection'], args.value['isRotateFlipCollection'],
162
- args.value['obj']);
163
- break;
164
- case 'selectShape':
165
- this.selectShape(args.value['id'], args.value['obj']);
166
- break;
167
- case 'deleteShape':
168
- this.deleteShape(args.value['id']);
169
- break;
170
- case 'getMaxText':
171
- this.getMaxText(args.value['isTextBox'], args.value['text'], args.value['obj']);
172
- break;
173
- case 'setPointCollForLineArrow':
174
- args.value['obj'].pointColl = this.getLinePoints(args.value['obj'].activePoint.startX,
175
- args.value['obj'].activePoint.startY, args.value['obj'].activePoint.endX,
176
- args.value['obj'].activePoint.endY);
177
- break;
178
- case 'setPointCollForShapeRotation':
179
- this.setPointCollForShapeRotation(args.value['obj']);
180
- break;
181
- case 'setTextSettings':
182
- if (args.value['textSettings']) {
183
- this.textSettings = args.value['textSettings'];
184
- } else if (args.value['fontFamily']) {
185
- this.textSettings.fontFamily = args.value['fontFamily'];
186
- } else if (args.value['fontSize']) {
187
- this.textSettings.fontSize = args.value['fontSize'];
188
- } else if (args.value['radius']) {
189
- this.strokeSettings.radius = args.value['radius'];
190
- }
191
- break;
192
- case 'setStrokeSettings':
193
- if (args.value['strokeSettings']) {
194
- this.strokeSettings = args.value['strokeSettings'];
195
- } else if (args.value['strokeColor']) {
196
- this.strokeSettings.strokeColor = args.value['strokeColor'];
197
- } else if (args.value['fillColor']) {
198
- this.strokeSettings.fillColor = args.value['fillColor'];
199
- } else if (args.value['strokeWidth']) {
200
- this.strokeSettings.strokeWidth = args.value['strokeWidth'];
201
- } else if (args.value['outlineColor']) {
202
- this.strokeSettings.outlineColor = args.value['outlineColor'];
203
- } else if (args.value['radius']) {
204
- this.strokeSettings.radius = args.value['radius'];
205
- } else if (args.value['outlineWidth']) {
206
- this.strokeSettings.outlineWidth = args.value['outlineWidth'];
207
- }
208
- break;
209
- case 'getStrokeSettings':
210
- args.value['obj']['strokeSettings'] = this.strokeSettings;
211
- break;
212
- case 'setKeyHistory':
213
- this.keyHistory = args.value['keyHistory'];
214
- break;
215
- case 'getKeyHistory':
216
- args.value['obj']['keyHistory'] = this.keyHistory;
217
- break;
218
- case 'setTextBoxPos':
219
- this.setTextBoxPos(args.value['actObj'], args.value['degree'], args.value['flip'], args.value['x'], args.value['y']);
220
- break;
221
- case 'setTextBoxPoints':
222
- this.setTextBoxPoints(args.value['actObj'], args.value['degree'], args.value['flip'], args.value['x'], args.value['y']);
223
- break;
224
- case 'alignTextAreaIntoCanvas':
225
- this.alignTextAreaIntoCanvas();
226
- break;
227
- case 'initializeTextShape':
228
- this.initializeTextShape(args.value['text'], args.value['fontFamily'], args.value['fontSize'],
229
- args.value['bold'], args.value['italic'], args.value['underline'], args.value['strikethrough'], args.value['strokeColor'],
230
- args.value['fillColor'], args.value['outlineColor'], args.value['outlineWidth']);
231
- break;
232
- case 'stopPathDrawing':
233
- this.stopPathDrawing(args.value['e'], args.value['isApply']);
234
- break;
235
- case 'updateArrowRatio':
236
- this.updateArrowRatio(args.value['obj']);
237
- break;
238
- case 'getSquarePointForRotatedShape':
239
- this.getSquarePointForRotatedShape(args.value['obj'], args.value['object']);
240
- break;
241
- case 'drawImage':
242
- this.drawImage(args.value['x'], args.value['y'], args.value['width'], args.value['height'],
243
- args.value['src'], args.value['degree'], args.value['isAspectRatio'], args.value['opacity'],
244
- args.value['isSelected']);
245
- break;
246
- case 'reset':
247
- this.reset();
248
- break;
249
- case 'updateObj':
250
- this.updateObj(args.value['dimObj'], args.value['x'], args.value['y']);
251
- break;
252
- case 'straightenShapes':
253
- this.straightenShapes();
254
- break;
255
- case 'straightenShapePoints':
256
- this.straightenShapePoints(args.value['obj'], args.value['isReverse']);
257
- break;
258
- case 'straightenPath':
259
- this.straightenPath(args.value['obj']);
260
- break;
261
- case 'straightenFHD':
262
- this.straightenFHD();
263
- break;
264
- case 'getTextBoxPosition':
265
- this.getTextBoxPosition(args.value['obj'], args.value['object']);
266
- break;
267
- case 'setFlipState':
268
- this.setFlipState(args.value['x'], args.value['y'], args.value['obj'], args.value['object']);
269
- break;
270
- case 'getNewShapeId':
271
- args.value['obj']['id'] = this.getNewShapeId();
272
- break;
273
- case 'z-order':
274
- this.updateZOrder(args.value['obj'], args.value['value']);
275
- break;
276
- case 'getSmallestIndex':
277
- args.value['obj']['index'] = this.getSmallestIndex();
278
- break;
279
- case 'isIndexInObjColl':
280
- args.value['obj']['bool'] = this.isIndexInObjColl(args.value['index']);
281
- break;
282
- case 'drawAnnotations':
283
- this.drawAnnotations(args.value['ctx'], args.value['shape'], args.value['pen'],
284
- args.value['isPreventApply'], args.value['x'], args.value['y'], args.value['panRegion']);
285
- break;
286
- case 'updateShapeColl':
287
- this.updateShapeColl();
288
- break;
289
- case 'getNewOrder':
290
- args.value['obj']['order'] = this.getNewOrder();
291
- break;
292
- case 'getHighestOrder':
293
- args.value['obj']['order'] = this.getHighestOrder();
294
- break;
295
- case 'getLowestOrder':
296
- args.value['obj']['order'] = this.getLowestOrder();
297
- break;
298
- case 'drawRedact':
299
- this.drawRedact(args.value['x'], args.value['y'], args.value['width'], args.value['height'],
300
- args.value['type'], args.value['value']);
301
- break;
302
- case 'setRedactType':
303
- this.redactType = args.value['redactType'];
304
- break;
305
- }
306
- }
307
-
308
- public getModuleName(): string {
309
- return 'shape';
310
- }
311
-
312
- private initShapePvtProps(): void {
313
- const parent: ImageEditor = this.parent;
314
- if (parent.lowerCanvas) {this.lowerContext = parent.lowerCanvas.getContext('2d'); }
315
- if (parent.upperCanvas) {this.upperContext = parent.upperCanvas.getContext('2d'); }
316
- if (isNullOrUndefined(this.shapeImg)) {
317
- this.shapeImg = parent.createElement('img', {
318
- id: parent.element.id + '_shapeImg', attrs: { name: 'Image', crossorigin: 'anonymous' }
319
- });
320
- }
321
- if (this.textSettings.fontFamily === '') {
322
- this.textSettings.fontFamily = parent.fontFamily.default;
323
- }
324
- }
325
-
326
- private reset(): void {
327
- this.textSettings =
328
- {text: 'Enter Text', fontFamily: this.parent.fontFamily.default, fontSize: null, fontRatio: null, bold: false, italic: false, underline: false, strikethrough: false};
329
- this.strokeSettings = {strokeColor: '#fff', fillColor: '', strokeWidth: null, radius: null, outlineColor: '', outlineWidth: null};
330
- this.preventFrameAnnotation = false;
331
- }
332
-
333
- private drawEllipse(x?: number, y?: number, radiusX?: number, radiusY?: number, strokeWidth?: number, strokeColor?: string,
334
- fillColor?: string, degree?: number, isSelected?: boolean): void {
335
- this.initializeShape('ellipse');
336
- const start: Point = x && y ? {x: x, y: y} : null;
337
- this.drawShape('ellipse', strokeWidth, strokeColor, fillColor, start, radiusX, radiusY,
338
- null, null, null, degree, null, isSelected);
339
- }
340
-
341
- private drawLine(startX?: number, startY?: number, endX?: number, endY?: number, strokeWidth?: number,
342
- strokeColor?: string, isSelected?: boolean): void {
343
- this.initializeShape('line');
344
- const start: Point = startX && startY ? {x: startX, y: startY} : null;
345
- const width: number = endX - startX; const height: number = endY - startY;
346
- this.drawShape('line', strokeWidth, strokeColor, null, start, width, height, null, null, null, null, null, isSelected);
347
- }
348
-
349
- private drawPath(pointColl: Point[], strokeWidth?: number, strokeColor?: string, isSelected?: boolean): void {
350
- this.initializeShape('path');
351
- if (pointColl) {
352
- this.drawShape('path', strokeWidth, strokeColor, null, null, null, null, pointColl, null, null, null, null, isSelected);
353
- }
354
- }
355
-
356
- private drawArrow(startX?: number, startY?: number, endX?: number, endY?: number, strokeWidth?: number,
357
- strokeColor?: string, arrowStart?: ArrowheadType, arrowEnd?: ArrowheadType, isSelected?: boolean): void {
358
- this.initializeShape('arrow');
359
- const start: Point = startX && startY ? {x: startX, y: startY} : null;
360
- const width: number = endX - startX; const height: number = endY - startY;
361
- this.drawShape('arrow', strokeWidth, strokeColor, null, start, width, height, null, arrowStart, arrowEnd, null, null, isSelected);
362
- }
363
-
364
- private drawRectangle(x?: number, y?: number, width?: number, height?: number, strokeWidth?: number, strokeColor?: string,
365
- fillColor?: string, degree?: number, isSelected?: boolean, radius?: number): void {
366
- this.initializeShape('rectangle');
367
- const start: Point = x && y ? {x: x, y: y} : null;
368
- this.drawShape('rectangle', strokeWidth, strokeColor, fillColor, start, width, height, null,
369
- null, null, degree, null, isSelected, radius);
370
- }
371
-
372
- // eslint-disable-next-line @typescript-eslint/tslint/config
373
- private drawRedact(x?: number, y?: number, width?: number, height?: number, type?: RedactType, value?: number) {
374
- this.initializeShape('redact');
375
- const start: Point = x && y ? {x: x, y: y} : null;
376
- this.drawShape('redact', null, null, null, start, width, height, null,
377
- null, null, null, null, null, null, type, value);
378
- }
379
-
380
- private drawText(x?: number, y?: number, text?: string, fontFamily?: string, fontSize?: number, bold?: boolean, italic?: boolean,
381
- color?: string, isSelected?: boolean, degree?: number, fillColor?: string, outlineColor?: string,
382
- outlineWidth?: number, transformCollection?: TransformationCollection[], underline?: boolean,
383
- strikethrough?: boolean): void {
384
- this.drawShapeText(text, fontFamily, fontSize, bold, italic, color, x, y, isSelected, degree,
385
- fillColor, outlineColor, outlineWidth, transformCollection, underline, strikethrough);
386
- }
387
-
388
- private initializeShape(type: string): void {
389
- const parent: ImageEditor = this.parent;
390
- this.redrawActObj();
391
- parent.activeObj.shape = type;
392
- parent.currObjType.isCustomCrop = false;
393
- }
394
-
395
- private updateWidthHeight(obj: SelectionPoint): SelectionPoint {
396
- obj.activePoint.width = obj.activePoint.endX - obj.activePoint.startX;
397
- obj.activePoint.height = obj.activePoint.endY - obj.activePoint.startY;
398
- return obj;
399
- }
400
-
401
- private setDimension(width: number, height: number): void {
402
- const parent: ImageEditor = this.parent;
403
- const shape: string = parent.activeObj.shape;
404
- if ((width && height) || ((shape === 'line' || shape === 'arrow') && (width || height))) {
405
- parent.activeObj.activePoint.width = width; parent.activeObj.activePoint.height = height;
406
- if (parent.currObjType.shape.toLowerCase() === 'ellipse') {
407
- parent.activeObj.activePoint.width = 2 * width;
408
- parent.activeObj.activePoint.height = 2 * height;
409
- }
410
- }
411
- }
412
-
413
- private getArrowType(type: ArrowheadType): string {
414
- let arrowType: string = type;
415
- if (type) {
416
- const typeToArrowType: Object = {'None': 'none', 'Arrow': 'arrow', 'SolidArrow': 'arrowSolid',
417
- 'Circle': 'circle', 'SolidCircle': 'circleSolid', 'Square': 'square', 'SolidSquare': 'squareSolid', 'Bar': 'bar' };
418
- arrowType = typeToArrowType[`${type}`];
419
- }
420
- return arrowType;
421
- }
422
-
423
- private drawShape(type: string, strokeWidth?: number, strokeColor?: string, fillColor?: string, start?: Point, width?: number,
424
- height?: number, pointColl?: Point[], arrowStart?: ArrowheadType, arrowEnd?: ArrowheadType, degree?: number,
425
- opacity?: number, isSelected?: boolean, radius?: number, redactType?: RedactType, value?: number): void {
426
- const parent: ImageEditor = this.parent;
427
- if (!parent.disabled && parent.isImageLoaded) {
428
- parent.notify('draw', { prop: 'setImageEdited', onPropertyChange: false });
429
- this.redrawActObj();
430
- const objColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
431
- parent.togglePen = false; this.keyHistory = '';
432
- parent.upperCanvas.style.display = 'block'; this.refreshActiveObj();
433
- parent.currObjType.shape = type = type.toLowerCase();
434
- if (type !== 'freehanddraw' && type !== '') {
435
- parent.activeObj.shape = type;
436
- let strokeSettings: StrokeSettings = parent.activeObj.strokeSettings;
437
- this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
438
- if (isNullOrUndefined(strokeSettings)) {
439
- strokeSettings = this.strokeSettings;
440
- }
441
- if (type === 'path' && pointColl) {
442
- parent.activeObj.pointColl = pointColl;
443
- }
444
- if (opacity !== null && opacity !== undefined) {parent.activeObj.opacity = opacity; }
445
- strokeSettings.strokeWidth = strokeWidth ? strokeWidth : strokeSettings.strokeWidth;
446
- const shape: string = parent.activeObj.shape;
447
- if ((shape === 'rectangle' || shape === 'ellipse') && strokeWidth === 0) {
448
- strokeSettings.strokeWidth = 0;
449
- }
450
- strokeSettings.strokeColor = strokeColor ? strokeColor : strokeSettings.strokeColor;
451
- strokeSettings.fillColor = fillColor || fillColor === '' ? fillColor : strokeSettings.fillColor;
452
- strokeSettings.radius = radius ? radius : strokeSettings.radius;
453
- const tempWidth: number = parent.img.destWidth > 100 ? 100 : parent.img.destWidth / 2;
454
- const tempHeight: number = parent.img.destHeight > 100 ? 100 : parent.img.destHeight / 2;
455
- parent.activeObj.activePoint.width = tempWidth; parent.activeObj.activePoint.height = tempHeight;
456
- if (type === 'line' || type === 'arrow') {
457
- parent.activeObj.lineDraw = 'horizontal'; parent.activeObj.activePoint.height = 0;
458
- if (type === 'arrow') {
459
- parent.activeObj.activePoint.width += 50;
460
- parent.activeObj.start = this.getArrowType(arrowStart); parent.activeObj.end = this.getArrowType(arrowEnd);
461
- }
462
- } else if (type === 'rectangle') {
463
- parent.activeObj.activePoint.width += parent.activeObj.activePoint.width / 2;
464
- } else if (type === 'redact') {
465
- if (redactType) {
466
- parent.activeObj.redactType = redactType.toLowerCase();
467
- if (redactType === RedactType.Blur) {
468
- if (value) {
469
- parent.activeObj.redactBlur = value;
470
- }
471
- } else {
472
- if (value) {
473
- parent.activeObj.redactPixelate = value;
474
- }
475
- }
476
- parent.activeObj.redactImage = parent.createElement('canvas');
477
- }
478
- }
479
- this.setDimension(width, height);
480
- if (start) {
481
- parent.activeObj.activePoint.startX = start.x; parent.activeObj.activePoint.startY = start.y;
482
- parent.activeObj.activePoint.endX = parent.activeObj.activePoint.startX +
483
- parent.activeObj.activePoint.width;
484
- parent.activeObj.activePoint.endY = parent.activeObj.activePoint.startY +
485
- parent.activeObj.activePoint.height;
486
- } else {
487
- this.setCenterPoints();
488
- }
489
- this.setPointCollForLineAndArrow();
490
- if (type === 'arrow') {
491
- parent.activeObj.triangleDirection = 'right';
492
- }
493
- parent.currObjType.isDragging = parent.currObjType.isCustomCrop = false;
494
- this.initShapeProps();
495
- const obj: Object = {shapeSettingsObj: {} as ShapeSettings };
496
- parent.notify('selection', { prop: 'updatePrevShapeSettings', onPropertyChange: false, value: {obj: obj}});
497
- const shapeSettings: ShapeSettings = obj['shapeSettingsObj'];
498
- const shapeChangingArgs: ShapeChangeEventArgs = {cancel: false, action: 'insert', previousShapeSettings: shapeSettings,
499
- currentShapeSettings: shapeSettings};
500
- parent.trigger('shapeChanging', shapeChangingArgs);
501
- parent.editCompleteArgs = shapeChangingArgs;
502
- this.updateShapeChangeEventArgs(shapeChangingArgs.currentShapeSettings, shapeChangingArgs.allowShapeOverflow);
503
- this.setDimension(width, height);
504
- parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate'}});
505
- if (degree) {
506
- parent.activeObj.rotatedAngle = degree * (Math.PI / 180);
507
- parent.notify('selection', {prop: 'updPtCollForShpRot', onPropertyChange: false, value: {obj: parent.activeObj }});
508
- }
509
- parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: {isPenEdit: null} });
510
- parent.notify('selection', { prop: 'isShapeInserted', onPropertyChange: false, value: {bool: true} });
511
- parent.notify('undo-redo', { prop: 'updateUrObj', onPropertyChange: false, value: {objColl: objColl}});
512
- if (type === 'redact') {
513
- parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'redact',
514
- isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
515
- } else {
516
- parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'shapes',
517
- isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
518
- }
519
- parent.notify('toolbar', { prop: 'update-toolbar-items', onPropertyChange: false});
520
- if (parent.isPublicMethod && !isSelected) {
521
- parent.notify('undo-redo', {prop: 'updateUndoRedo', value: {operation: 'shapeInsert'}, onPropertyChange: false});
522
- }
523
- parent.isPublicMethod = false;
524
- }
525
- }
526
- }
527
-
528
- private initShapeProps(): void {
529
- const parent: ImageEditor = this.parent;
530
- parent.activeObj.shapeDegree = parent.transform.degree;
531
- parent.activeObj.shapeFlip = parent.transform.currFlipState;
532
- parent.activeObj.textFlip = parent.transform.currFlipState;
533
- parent.activeObj.flipObjColl = [];
534
- parent.activeObj.order = this.getNewOrder();
535
- }
536
-
537
- private setPointCollForLineAndArrow(): void {
538
- const parent: ImageEditor = this.parent;
539
- const shape: string = parent.activeObj.shape;
540
- const {startX, startY, endX, endY} : ActivePoint = parent.activeObj.activePoint;
541
- if (shape === 'line' || shape === 'arrow') {
542
- parent.activeObj.pointColl = this.getLinePoints(startX, startY, endX, endY);
543
- if (parent.activeObj.pointColl) {
544
- for (let i: number = 0, len: number = parent.activeObj.pointColl.length; i < len; i++) {
545
- parent.activeObj.pointColl[i as number].ratioX = (parent.activeObj.pointColl[i as number].x -
546
- parent.img.destLeft) / parent.img.destWidth;
547
- parent.activeObj.pointColl[i as number].ratioY = (parent.activeObj.pointColl[i as number].y -
548
- parent.img.destTop) / parent.img.destHeight;
549
- }
550
- }
551
- }
552
- }
553
-
554
- private prevObjColl(): void {
555
- const parent: ImageEditor = this.parent;
556
- const object: Object = {currObj: {} as CurrentObject };
557
- parent.notify('filter', { prop: 'getCurrentObj', onPropertyChange: false, value: {object: object }});
558
- this.prevObj = object['currObj'];
559
- this.prevObj.objColl = extend([], parent.objColl, [], true) as SelectionPoint[];
560
- this.prevObj.pointColl = extend([], parent.pointColl, [], true) as Point[];
561
- this.prevObj.afterCropActions = extend([], parent.afterCropActions, [], true) as string[];
562
- const selPointCollObj: Object = {selPointColl: null };
563
- parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
564
- value: {obj: selPointCollObj }});
565
- this.prevObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true) as Point[];
566
- }
567
-
568
- private drawShapeText(text?: string, fontFamily?: string, fontSize?: number, bold?: boolean, italic?: boolean,
569
- strokeColor?: string, x?: number, y?: number, isSelected?: boolean, degree?: number, fillColor?: string,
570
- outlineColor?: string, outlineWidth?: number, transformCollection?: TransformationCollection[],
571
- underline?: boolean, strikethrough?: boolean): void {
572
- const parent: ImageEditor = this.parent;
573
- if (!parent.disabled && parent.isImageLoaded) {
574
- if (parent.currObjType.shape === 'freehanddraw') {
575
- this.apply();
576
- parent.upperCanvas.style.cursor = parent.cursor = 'default';
577
- parent.currObjType.shape = '';
578
- }
579
- parent.notify('draw', { prop: 'setImageEdited', onPropertyChange: false });
580
- parent.togglePen = false; this.redrawActObj();
581
- this.prevObjColl();
582
- this.refreshActiveObj(); parent.activeObj.shape = parent.currObjType.shape = 'text';
583
- parent.currObjType.isCustomCrop = false;
584
- this.initializeTextShape(text, fontFamily, fontSize, bold, italic, underline, strikethrough, strokeColor, fillColor,
585
- outlineColor, outlineWidth);
586
- parent.currObjType.isText = parent.currObjType.isInitialText = true;
587
- if (isNullOrUndefined(parent.activeObj.textSettings.fontSize)) {
588
- parent.getFontSizes();
589
- parent.activeObj.textSettings.fontSize = parseInt(parent.fontSizeColl[(parseInt('3', 10) - 1)].text, 10);
590
- }
591
- if (parent.img.destWidth < 100) {
592
- parent.activeObj.textSettings.fontSize = Math.floor((parent.img.destWidth / 20));
593
- } else if (parent.img.destHeight < 100) {
594
- parent.activeObj.textSettings.fontSize = Math.floor((parent.img.destHeight / 20));
595
- }
596
- parent.activeObj.shapeDegree = parent.transform.degree;
597
- parent.activeObj.shapeFlip = parent.transform.currFlipState;
598
- parent.activeObj.flipObjColl = []; this.updateFontStyles();
599
- parent.activeObj.order = this.getNewOrder();
600
- let width: number = this.upperContext.measureText(parent.activeObj.textSettings.text).width +
601
- parent.activeObj.textSettings.fontSize * 0.5;
602
- let height: number = parent.activeObj.textSettings.fontSize;
603
- if (text) {
604
- parent.activeObj.keyHistory = text;
605
- let maxText: string = this.getMaxText();
606
- maxText = maxText ? maxText : parent.activeObj.textSettings.text;
607
- width = this.upperContext.measureText(maxText).width + parent.activeObj.textSettings.fontSize * 0.5;
608
- const rows: string[] = text.split('\n');
609
- if (rows.length > 1) {
610
- height = rows.length * parent.activeObj.textSettings.fontSize;
611
- height += (fontSize * 0.25);
612
- }
613
- }
614
- if (!isNullOrUndefined(x) && !isNullOrUndefined(y)) {
615
- parent.activeObj.activePoint.startX = x; parent.activeObj.activePoint.startY = y;
616
- parent.activeObj.activePoint.endX = parent.activeObj.activePoint.startX + width;
617
- parent.activeObj.activePoint.endY = parent.activeObj.activePoint.startY + height;
618
- } else {
619
- this.setCenterPoints(true, width, height);
620
- }
621
- if (transformCollection) {
622
- parent.notify('selection', { prop: 'setTransformedShape', onPropertyChange: false, value: {bool: true}});
623
- this.setTransformColl(transformCollection);
624
- const actObj: SelectionPoint = parent.activeObj;
625
- actObj.shapeDegree = 0;
626
- actObj.shapeFlip = '';
627
- let tempDegree: number = 0;
628
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
629
- const coll: any = actObj.rotateFlipColl;
630
- for (let i: number = 0; i < coll.length; i++) {
631
- if (typeof(coll[i as number]) === 'number') {
632
- tempDegree += coll[i as number];
633
- }
634
- }
635
- if (tempDegree % 90 === 0 && Math.abs(tempDegree) % 180 === 90) {
636
- actObj.activePoint.endX = actObj.activePoint.startX + height;
637
- actObj.activePoint.endY = actObj.activePoint.startY + width;
638
- actObj.activePoint.width = actObj.activePoint.endX - actObj.activePoint.startX;
639
- actObj.activePoint.height = actObj.activePoint.endY - actObj.activePoint.startY;
640
- }
641
- }
642
- const obj: Object = {shapeSettingsObj: {} as ShapeSettings };
643
- parent.notify('selection', { prop: 'updatePrevShapeSettings', onPropertyChange: false, value: {obj: obj}});
644
- const shapeSettings: ShapeSettings = obj['shapeSettingsObj'];
645
- const shapeChangingArgs: ShapeChangeEventArgs = {cancel: false, action: 'insert', previousShapeSettings: shapeSettings,
646
- currentShapeSettings: shapeSettings};
647
- parent.trigger('shapeChanging', shapeChangingArgs);
648
- parent.editCompleteArgs = shapeChangingArgs;
649
- this.drawShapeTextEvent(shapeChangingArgs);
650
- if (degree) {
651
- parent.activeObj.rotatedAngle = degree * (Math.PI / 180);
652
- parent.notify('selection', { prop: 'updPtCollForShpRot', onPropertyChange: false, value: { obj: parent.activeObj } });
653
- this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
654
- parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: { canvas: 'duplicate', obj: parent.activeObj, isCropRatio: null,
655
- points: null, isPreventDrag: true, saveContext: null, isPreventSelection: null } });
656
- parent.notify('toolbar', { prop: 'destroy-qa-toolbar', onPropertyChange: false });
657
- parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: { isPenEdit: null } });
658
- }
659
- if (text && text.indexOf('\n') > -1 && parent.isPublicMethod) {
660
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
661
- const fontSizeInd: string = String((parent.fontSizeColl as any).findIndex(
662
- (item: { text: string; }) => item.text === String(parent.activeObj.textSettings.fontSize)) + 1);
663
- parent.noPushUndo = true;
664
- parent.updateFontSize('5');
665
- if (parseInt(fontSizeInd, 10) > 0) {
666
- parent.updateFontSize(fontSizeInd);
667
- }
668
- parent.noPushUndo = false;
669
- }
670
- if (parent.isPublicMethod && !isSelected) {
671
- parent.notify('undo-redo', {prop: 'updateUndoRedo', value: {operation: 'shapeInsert'}, onPropertyChange: false});
672
- }
673
- parent.isPublicMethod = false;
674
- }
675
- }
676
-
677
- private drawShapeImageEvent(shapeChangingArgs: ShapeChangeEventArgs, isSelect: boolean): void {
678
- const parent: ImageEditor = this.parent;
679
- this.updateShapeChangeEventArgs(shapeChangingArgs.currentShapeSettings, shapeChangingArgs.allowShapeOverflow);
680
- parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate' }});
681
- parent.objColl.push(parent.activeObj);
682
- const prevCropObj: CurrentObject = extend({}, parent.cropObj, {}, true) as CurrentObject;
683
- parent.notify('undo-redo', { prop: 'updateUndoRedoColl', onPropertyChange: false,
684
- value: {operation: 'shapeInsert', previousObj: this.prevObj, previousObjColl: this.prevObj.objColl,
685
- previousPointColl: this.prevObj.pointColl, previousSelPointColl: this.prevObj.selPointColl, previousCropObj: prevCropObj,
686
- previousText: null, currentText: null, previousFilter: null, isCircleCrop: null}});
687
- parent.notify('selection', { prop: 'redrawShape', onPropertyChange: false,
688
- value: {obj: parent.objColl[parent.objColl.length - 1]}});
689
- if (isSelect) {
690
- parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'shapes',
691
- isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
692
- parent.notify('toolbar', { prop: 'update-toolbar-items', onPropertyChange: false});
693
- parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: {isPenEdit: null} });
694
- } else {
695
- parent.okBtn(null, true);
696
- }
697
- parent.notify('selection', { prop: 'isShapeInserted', onPropertyChange: false, value: {bool: true} });
698
- }
699
-
700
- private setTransformColl(transformCollection: TransformationCollection[]): void {
701
- const parent: ImageEditor = this.parent;
702
- parent.activeObj.rotateFlipColl = [];
703
- if (transformCollection) {
704
- for (let i: number = 0; i < transformCollection.length; i++) {
705
- if (transformCollection[i as number].degree) {
706
- parent.activeObj.rotateFlipColl.push(transformCollection[i as number].degree);
707
- } else {
708
- parent.activeObj.rotateFlipColl.push(transformCollection[i as number].flip.toLowerCase());
709
- }
710
- }
711
- }
712
- }
713
-
714
- private drawShapeTextEvent(shapeChangingArgs: ShapeChangeEventArgs): void {
715
- const parent: ImageEditor = this.parent;
716
- this.updateShapeChangeEventArgs(shapeChangingArgs.currentShapeSettings, shapeChangingArgs.allowShapeOverflow);
717
- this.addLetter(parent.activeObj.textSettings.text);
718
- parent.activeObj.textFlip = parent.transform.currFlipState;
719
- this.updateFontRatio(parent.activeObj);
720
- parent.objColl.push(parent.activeObj);
721
- const prevCropObj: CurrentObject = extend({}, parent.cropObj, {}, true) as CurrentObject;
722
- parent.notify('undo-redo', { prop: 'updateUndoRedoColl', onPropertyChange: false,
723
- value: {operation: 'shapeInsert', previousObj: this.prevObj, previousObjColl: this.prevObj.objColl,
724
- previousPointColl: this.prevObj.pointColl, previousSelPointColl: this.prevObj.selPointColl,
725
- previousCropObj: prevCropObj, previousText: null, currentText: null, previousFilter: null, isCircleCrop: null}});
726
- parent.notify('selection', { prop: 'redrawShape', onPropertyChange: false,
727
- value: {obj: parent.objColl[parent.objColl.length - 1]}});
728
- parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: {isPenEdit: null} });
729
- parent.notify('selection', { prop: 'isShapeInserted', onPropertyChange: false, value: {bool: true} });
730
- parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'text',
731
- isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
732
- parent.notify('toolbar', { prop: 'update-toolbar-items', onPropertyChange: false});
733
- }
734
-
735
- private initializeTextShape(
736
- text?: string, fontFamily?: string, fontSize?: number, bold?: boolean, italic?: boolean,
737
- underline?: boolean, strikethrough?: boolean, strokeColor?: string, fillColor?: string, outlineColor?: string, outlineWidth?: number
738
- ): void {
739
- const parent: ImageEditor = this.parent;
740
- this.keyHistory = ''; parent.upperCanvas.style.display = 'block';
741
- parent.activeObj.strokeSettings.strokeColor = strokeColor || parent.activeObj.strokeSettings.strokeColor;
742
- parent.activeObj.strokeSettings.fillColor = fillColor || parent.activeObj.strokeSettings.fillColor;
743
- parent.activeObj.textSettings.text = text || parent.activeObj.textSettings.text;
744
- parent.activeObj.textSettings.fontFamily = fontFamily || parent.activeObj.textSettings.fontFamily;
745
- parent.activeObj.textSettings.fontSize = fontSize || parent.activeObj.textSettings.fontSize;
746
- parent.activeObj.textSettings.bold = bold || parent.activeObj.textSettings.bold;
747
- parent.activeObj.textSettings.italic = italic || parent.activeObj.textSettings.italic;
748
- parent.activeObj.textSettings.underline = underline || parent.activeObj.textSettings.underline;
749
- parent.activeObj.textSettings.strikethrough = strikethrough || parent.activeObj.textSettings.strikethrough;
750
- parent.activeObj.strokeSettings.outlineColor = outlineColor || parent.activeObj.strokeSettings.outlineColor;
751
- parent.activeObj.strokeSettings.outlineWidth = outlineWidth || parent.activeObj.strokeSettings.outlineWidth;
752
- }
753
-
754
- private drawImage(x: number, y: number, width: number, height: number, src: string | ImageData, degree: number,
755
- isAspectRatio: boolean, opacity?: number, isSelected?: boolean): void {
756
- this.initializeShape('image');
757
- this.onLoadImgShape(x, y, width, height, src, null, degree, isAspectRatio, opacity, isSelected);
758
- }
759
-
760
- private redrawActObj(x?: number, y?: number, isMouseDown?: boolean): void {
761
- let splitWords: string[];
762
- const parent: ImageEditor = this.parent;
763
- if (parent.activeObj.shape) {splitWords = parent.activeObj.shape.split('-'); }
764
- if (parent.activeObj.horTopLine && (parent.activeObj.shape && splitWords[0] !== 'crop')) {
765
- if (parent.textArea.style.display === 'block' || parent.textArea.style.display === 'inline-block') {
766
- parent.notify('selection', { prop: 'setTextBoxStylesToActObj', onPropertyChange: false });
767
- this.updateFontRatio(parent.activeObj, true);
768
- if (x && y) {
769
- if ((x !== parent.activeObj.activePoint.startX) && (y !== parent.activeObj.activePoint.startY)) {
770
- this.updateTextFromTextArea();
771
- }
772
- } else {
773
- this.updateTextFromTextArea();
774
- parent.textArea.style.transform = '';
775
- parent.notify('toolbar', { prop: 'refresh-main-toolbar', onPropertyChange: false});
776
- }
777
- this.refreshActiveObj();
778
- } else {
779
- this.applyActObj(isMouseDown);
780
- }
781
- }
782
- }
783
-
784
- private apply(shape?: string, obj?: SelectionPoint, canvas?: string): void {
785
- const parent: ImageEditor = this.parent;
786
- if (!parent.disabled) {
787
- if (parent.togglePen && !parent.currObjType.isCustomCrop) {
788
- const destLeft: number = parent.img.destLeft; const destTop: number = parent.img.destTop;
789
- const destWidth: number = parent.img.destWidth; const destHeight: number = parent.img.destHeight;
790
- parent.notify('draw', { prop: 'callUpdateCurrTransState', onPropertyChange: false});
791
- const temp: string = this.lowerContext.filter; this.lowerContext.filter = 'none';
792
- parent.togglePen = false;
793
- if (parent.isCircleCrop || (parent.currSelectionPoint &&
794
- parent.currSelectionPoint.shape === 'crop-circle')) {
795
- parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
796
- value: {context: this.lowerContext, isSave: null, isFlip: null}});
797
- }
798
- parent.img.destLeft = destLeft; parent.img.destTop = destTop; parent.img.destWidth = destWidth;
799
- parent.img.destHeight = destHeight; this.lowerContext.filter = temp;
800
- }
801
- else {
802
- canvas = canvas ? canvas : 'original';
803
- if (isNullOrUndefined(parent.activeObj.shape) && isNullOrUndefined(shape)) {
804
- parent.currObjType.shape = '';
805
- } else {
806
- parent.currObjType.shape = shape || parent.currObjType.shape;
807
- }
808
- if (parent.currObjType.shape !== '') {
809
- this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
810
- if (parent.activeObj.shape === 'text') {
811
- parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: canvas, obj: obj, isCropRatio: null,
812
- points: null, isPreventDrag: true, saveContext: null, isPreventSelection: null} });
813
- } else {
814
- parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: canvas, obj: obj} });
815
- }
816
- parent.activeObj.shape = parent.currObjType.shape.toLowerCase();
817
- if (!shape && parent.currObjType.shape !== '' && !parent.currObjType.isCustomCrop) {
818
- parent.objColl.push(extend({}, parent.activeObj, {}, true) as SelectionPoint);
819
- }
820
- this.keyHistory = '';
821
- }
822
- }
823
- }
824
- }
825
-
826
- private setCenterPoints(text?: boolean, width?: number, height?: number): void {
827
- const parent: ImageEditor = this.parent;
828
- let renderWidth: number; let renderHeight: number;
829
- if (text && width && height) { renderWidth = width; renderHeight = height; }
830
- else {renderWidth = parent.activeObj.activePoint.width; renderHeight = parent.activeObj.activePoint.height; }
831
- parent.activeObj.activePoint.startX = (parent.lowerCanvas.width / 2) - renderWidth / 2;
832
- parent.activeObj.activePoint.startY = (parent.lowerCanvas.height / 2) - renderHeight / 2;
833
- parent.activeObj.activePoint.endX = (parent.lowerCanvas.width / 2) + renderWidth / 2;
834
- parent.activeObj.activePoint.endY = (parent.lowerCanvas.height / 2) + renderHeight / 2;
835
- }
836
-
837
- private updSelChangeEventArgs(selectionSettings: CropSelectionSettings): void {
838
- const parent: ImageEditor = this.parent;
839
- parent.activeObj.activePoint = { startX: selectionSettings.startX, startY: selectionSettings.startY,
840
- endX: parent.activeObj.activePoint.startX + parent.activeObj.activePoint.width,
841
- endY: parent.activeObj.activePoint.startY + parent.activeObj.activePoint.height,
842
- width: selectionSettings.width, height: selectionSettings.height };
843
- parent.activeObj.activePoint.endX = parent.activeObj.activePoint.startX + parent.activeObj.activePoint.width;
844
- parent.activeObj.activePoint.endY = parent.activeObj.activePoint.startY + parent.activeObj.activePoint.height;
845
- }
846
-
847
- private updateShapeChangeEventArgs(shapeSettings: ShapeSettings, allowShapeOverflow: boolean): void {
848
- const parent: ImageEditor = this.parent; let shapeId: number;
849
- if (shapeSettings.id && shapeSettings.id.indexOf('shape_') === -1 &&
850
- shapeSettings.id.indexOf('pen_') === -1) {
851
- if (parent.activeObj.currIndex) {
852
- parent.activeObj.currIndex = 'shape_' + shapeSettings.id;
853
- } else {
854
- parent.pointColl[shapeId as number].id = 'pen_' + shapeSettings.id;
855
- }
856
- }
857
- if (shapeSettings.id && shapeSettings.id.split('_')[0] && shapeSettings.id.split('_')[0] === 'pen') {
858
- shapeId = parseInt(shapeSettings.id.split('_')[1], 10) - 1;
859
- parent.pointColl[shapeId as number].points = shapeSettings.points;
860
- parent.pointColl[shapeId as number].strokeColor = shapeSettings.strokeColor;
861
- parent.pointColl[shapeId as number].strokeWidth = shapeSettings.strokeWidth;
862
- parent.pointColl[shapeId as number].opacity = shapeSettings.opacity;
863
- if (shapeSettings.index) {
864
- parent.pointColl[shapeId as number].order = shapeSettings.index;
865
- }
866
- } else {
867
- parent.activeObj.activePoint.startX = shapeSettings.startX;
868
- parent.activeObj.activePoint.startY = shapeSettings.startY;
869
- if (shapeSettings.width && shapeSettings.height) {
870
- parent.activeObj.activePoint.width = shapeSettings.width;
871
- parent.activeObj.activePoint.height = shapeSettings.height;
872
- parent.activeObj.activePoint.endX = parent.activeObj.activePoint.startX + parent.activeObj.activePoint.width;
873
- parent.activeObj.activePoint.endY = parent.activeObj.activePoint.startY + parent.activeObj.activePoint.height;
874
- }
875
- if (parent.activeObj.shape !== 'text') {
876
- parent.activeObj.strokeSettings.strokeColor = shapeSettings.strokeColor;
877
- parent.activeObj.strokeSettings.strokeWidth = shapeSettings.strokeWidth;
878
- }
879
- parent.activeObj.strokeSettings.fillColor = shapeSettings.fillColor;
880
- parent.activeObj.opacity = shapeSettings.opacity;
881
- if (shapeSettings.index) {
882
- parent.activeObj.order = shapeSettings.index;
883
- }
884
- parent.activeObj.preventShapeDragOut = !allowShapeOverflow;
885
- if (isNullOrUndefined(shapeSettings.degree)) { shapeSettings.degree = 0; }
886
- switch (parent.activeObj.shape) {
887
- case 'ellipse':
888
- parent.activeObj.activePoint.width = shapeSettings.radiusX * 2;
889
- parent.activeObj.activePoint.height = shapeSettings.radiusY * 2;
890
- parent.activeObj.activePoint.endX = parent.activeObj.activePoint.startX + parent.activeObj.activePoint.width;
891
- parent.activeObj.activePoint.endY = parent.activeObj.activePoint.startY + parent.activeObj.activePoint.height;
892
- if (shapeSettings.degree) {
893
- parent.activeObj.rotatedAngle = shapeSettings.degree * (Math.PI / 180);
894
- }
895
- break;
896
- case 'line':
897
- case 'arrow':
898
- parent.activeObj.activePoint.width = shapeSettings.length;
899
- parent.activeObj.activePoint.endX = shapeSettings.endX;
900
- parent.activeObj.activePoint.endY = shapeSettings.endY;
901
- parent.activeObj.activePoint.width = parent.activeObj.activePoint.startX + parent.activeObj.activePoint.width;
902
- parent.activeObj.activePoint.height = parent.activeObj.activePoint.startY + parent.activeObj.activePoint.height;
903
- if (parent.activeObj.shape === 'arrow') {
904
- parent.activeObj.start = this.getArrowType(shapeSettings.arrowHead);
905
- parent.activeObj.end = this.getArrowType(shapeSettings.arrowTail);
906
- }
907
- break;
908
- case 'text':
909
- parent.activeObj.keyHistory = parent.activeObj.textSettings.text = shapeSettings.text;
910
- parent.activeObj.textSettings.fontSize = shapeSettings.fontSize;
911
- parent.activeObj.strokeSettings.strokeColor = shapeSettings.color;
912
- parent.activeObj.strokeSettings.outlineColor = shapeSettings.strokeColor;
913
- parent.activeObj.strokeSettings.outlineWidth = shapeSettings.strokeWidth;
914
- parent.activeObj.strokeSettings.fillColor = shapeSettings.fillColor;
915
- parent.activeObj.textSettings.fontFamily = shapeSettings.fontFamily;
916
- this.setTransformColl(shapeSettings.transformCollection);
917
- if (shapeSettings.degree) {
918
- parent.activeObj.rotatedAngle = shapeSettings.degree * (Math.PI / 180);
919
- }
920
- this.updateFontRatio(parent.activeObj);
921
- break;
922
- case 'rectangle':
923
- case 'image':
924
- if (shapeSettings.degree) {
925
- parent.activeObj.rotatedAngle = shapeSettings.degree * (Math.PI / 180);
926
- }
927
- // Prevented setting image src as it cannot be set in canvas
928
- break;
929
- case 'path':
930
- parent.activeObj.pointColl = shapeSettings.points;
931
- break;
932
- }
933
- if (parent.activeObj.shape === 'text' && parent.activeObj.textSettings) {
934
- parent.activeObj.textSettings.bold = false; parent.activeObj.textSettings.italic = false;
935
- parent.activeObj.textSettings.underline = false; parent.activeObj.textSettings.strikethrough = false;
936
- for (let i: number = 0; i < shapeSettings.fontStyle.length; i++) {
937
- switch (shapeSettings.fontStyle[i as number]) {
938
- case 'bold':
939
- parent.activeObj.textSettings.bold = true;
940
- break;
941
- case 'italic':
942
- parent.activeObj.textSettings.italic = true;
943
- break;
944
- case 'underline':
945
- parent.activeObj.textSettings.underline = true;
946
- break;
947
- case 'strikethrough':
948
- parent.activeObj.textSettings.strikethrough = true;
949
- break;
950
- }
951
- }
952
- }
953
- }
954
- }
955
-
956
- private addLetter(letter: string): void {
957
- const parent: ImageEditor = this.parent;
958
- if (parent.textArea.style.display === 'none' && (parent.currObjType.isText || parent.activeObj.shape === 'text')) {
959
- const {fontSize} : TextSettings = parent.activeObj.textSettings;
960
- if (letter === 'Backspace') {this.keyHistory = this.keyHistory.slice(0, -1); }
961
- else {this.keyHistory += letter; }
962
- this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
963
- this.updateFontStyles();
964
- const width: number = this.upperContext.measureText(this.keyHistory).width + fontSize * 0.5;
965
- const height: number = fontSize * 1.18;
966
- this.upperContext.fillText(this.keyHistory, parent.activeObj.activePoint.startX,
967
- parent.activeObj.activePoint.startY + fontSize);
968
- this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
969
- parent.currObjType.isText = true;
970
- parent.notify('selection', { prop: 'setActivePoint', onPropertyChange: false,
971
- value: {startX: width, startY: height}});
972
- }
973
- }
974
-
975
- private redrawText(): void {
976
- const parent: ImageEditor = this.parent;
977
- const {fontSize, fontFamily, bold, italic } : TextSettings = parent.activeObj.textSettings;
978
- let fontStyle: string = '';
979
- if (bold) {
980
- fontStyle += 'bold ';
981
- }
982
- if (italic) {
983
- fontStyle += 'italic ';
984
- }
985
- this.upperContext.font = fontStyle + fontSize + 'px ' + fontFamily;
986
- const rows: string[] = parent.activeObj.keyHistory.split('\n');
987
- const text: string = (parent.textArea.style.display === 'block' || parent.textArea.style.display === 'inline-block') ?
988
- this.getMaxText(true) : this.getMaxText();
989
- const width: number = this.upperContext.measureText(text).width + fontSize * 0.5;
990
- let height: number = rows.length * fontSize * 1.18;
991
- if (rows.length > 1) {height += (fontSize * 0.50); }
992
- parent.notify('selection', { prop: 'setTextSelection', onPropertyChange: false,
993
- value: {width: width, height: height}});
994
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint: parent.activeObj.activePoint, obj: parent.activeObj,
995
- isMouseMove: null, x: null, y: null}});
996
- parent.notify('selection', { prop: 'redrawShape', onPropertyChange: false,
997
- value: {obj: parent.activeObj}});
998
- }
999
-
1000
- private updateTextFromTextArea(): void {
1001
- const parent: ImageEditor = this.parent; let allowUndoRedo: boolean = false;
1002
- const { fontSize } : TextSettings = parent.activeObj.textSettings;
1003
- const tempActiveObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
1004
- const prevCropObj: CurrentObject = extend({}, parent.cropObj, {}, true) as CurrentObject;
1005
- const object: Object = {currObj: {} as CurrentObject };
1006
- parent.notify('filter', { prop: 'getCurrentObj', onPropertyChange: false, value: {object: object }});
1007
- const prevObj: CurrentObject = object['currObj'];
1008
- prevObj.objColl = extend([], parent.objColl, [], true) as SelectionPoint[];
1009
- prevObj.pointColl = extend([], parent.pointColl, [], true) as Point[];
1010
- prevObj.afterCropActions = extend([], parent.afterCropActions, [], true) as string[];
1011
- const selPointCollObj: Object = {selPointColl: null };
1012
- parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
1013
- value: {obj: selPointCollObj }});
1014
- prevObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true) as Point[];
1015
- if (parent.activeObj.keyHistory !== parent.textArea.value) {
1016
- allowUndoRedo = true;
1017
- }
1018
- parent.activeObj.keyHistory = parent.textArea.value; parent.textArea.style.display = 'none';
1019
- parent.textArea.value = ''; this.updateFontStyles();
1020
- let width: number = this.upperContext.measureText(parent.activeObj.keyHistory).width + fontSize * 0.5;
1021
- let height: number = fontSize * 1.18;
1022
- const rows: string[] = parent.activeObj.keyHistory.split('\n');
1023
- if (rows.length > 1) {
1024
- height *= rows.length;
1025
- height += (fontSize * 0.1 * rows.length);
1026
- const widthColl: number[] = [];
1027
- for (let i: number = 0, len: number = rows.length; i < len; i++) {
1028
- widthColl.push(this.upperContext.measureText(rows[i as number]).width + fontSize * 0.5);
1029
- }
1030
- width = Math.max(...widthColl);
1031
- }
1032
- parent.notify('selection', { prop: 'setTextSelection', onPropertyChange: false,
1033
- value: {width: width, height: height}});
1034
- if (parent.activeObj.rotatedAngle !== 0) {
1035
- const width: number = parent.activeObj.activePoint.width - tempActiveObj.activePoint.width;
1036
- const height: number = parent.activeObj.activePoint.height - tempActiveObj.activePoint.height;
1037
- let value: string = '';
1038
- if (width > 0 && height > 0) {
1039
- value = 'widthHeight';
1040
- } else if (width !== 0) {
1041
- value = 'width';
1042
- } else if (height !== 0) {
1043
- value = 'height';
1044
- }
1045
- parent.activeObj.activePoint = extend({}, tempActiveObj.activePoint, {}, true) as ActivePoint;
1046
- parent.notify('selection', { prop: 'adjustRotationPoints', onPropertyChange: false, value: { rectangle: parent.activeObj.activePoint,
1047
- x: width, y: height, angle: parent.activeObj.rotatedAngle, type: 'text', elem: value }});
1048
- parent.notify('shape', { prop: 'updateFontSize', onPropertyChange: false,
1049
- value: {obj: parent.activeObj}});
1050
- }
1051
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint: parent.activeObj.activePoint, obj: parent.activeObj,
1052
- isMouseMove: null, x: null, y: null}});
1053
- this.updImgRatioForActObj();
1054
- if (parent.activeObj.rotatedAngle !== 0) {
1055
- parent.notify('selection', {prop: 'updPtCollForShpRot', onPropertyChange: false, value: {obj: parent.activeObj }});
1056
- }
1057
- if (allowUndoRedo) {
1058
- this.apply(parent.activeObj.shape, parent.activeObj);
1059
- parent.objColl.push(extend({}, parent.activeObj, {}, true) as SelectionPoint);
1060
- parent.notify('undo-redo', { prop: 'updateUndoRedoColl', onPropertyChange: false,
1061
- value: {operation: 'text', previousObj: prevObj, previousObjColl: prevObj.objColl,
1062
- previousPointColl: prevObj.pointColl, previousSelPointColl: prevObj.selPointColl,
1063
- previousCropObj: prevCropObj, previousText: parent.activeObj.keyHistory,
1064
- currentText: parent.textArea.value, previousFilter: null, isCircleCrop: null}});
1065
- } else {
1066
- this.apply(parent.activeObj.shape, parent.activeObj);
1067
- parent.objColl.push(extend({}, parent.activeObj, {}, true) as SelectionPoint);
1068
- }
1069
- }
1070
-
1071
- private iterateObjColl(): void {
1072
- const parent: ImageEditor = this.parent;
1073
- if (parent.objColl.length > 0) {
1074
- let index: number = this.getSmallestIndex();
1075
- const objColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
1076
- while (objColl.length > 0) {
1077
- let found: boolean = false;
1078
- for (let i: number = 0; i < objColl.length; i++) {
1079
- const currentObj: SelectionPoint = objColl[i as number];
1080
- if (isNullOrUndefined(currentObj.order)) {
1081
- objColl.splice(i, 1);
1082
- i--;
1083
- continue;
1084
- }
1085
- if (currentObj.order === index) {
1086
- this.apply(currentObj.shape, currentObj);
1087
- if (currentObj.shape === 'redact' && JSON.stringify(currentObj.activePoint) === JSON.stringify(parent.activeObj.activePoint) &&
1088
- currentObj.redactImage !== parent.activeObj.redactImage) {
1089
- currentObj.redactImage = parent.activeObj.redactImage;
1090
- if (parent.objColl[i as number] && JSON.stringify(parent.objColl[i as number].activePoint) ===
1091
- JSON.stringify(currentObj.activePoint)) {
1092
- parent.objColl[i as number].redactImage = parent.activeObj.redactImage;
1093
- }
1094
- }
1095
- this.refreshActiveObj();
1096
- index++;
1097
- if (!this.isIndexInObjColl(index)) {index++; }
1098
- objColl.splice(i, 1);
1099
- found = true;
1100
- break; // Exit the loop to start from the beginning
1101
- }
1102
- }
1103
- if (!found) {
1104
- break; // If no matching order was found, exit the loop
1105
- }
1106
- }
1107
- }
1108
- }
1109
-
1110
- private getSmallestIndex(): number {
1111
- const parent: ImageEditor = this.parent;
1112
- let smallestIndex: number;
1113
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1114
- const currentObj: SelectionPoint = parent.objColl[i as number];
1115
- if (isNullOrUndefined(currentObj.order)) {
1116
- continue;
1117
- }
1118
- if (isNullOrUndefined(smallestIndex) || currentObj.order < smallestIndex) {
1119
- smallestIndex = currentObj.order;
1120
- }
1121
- }
1122
- return smallestIndex;
1123
- }
1124
-
1125
- private isIndexInObjColl(index: number): boolean {
1126
- const parent: ImageEditor = this.parent;
1127
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1128
- const currentObj: SelectionPoint = parent.objColl[i as number];
1129
- if (isNullOrUndefined(currentObj.order)) {
1130
- continue;
1131
- }
1132
- if (currentObj.order === index) {
1133
- return true;
1134
- }
1135
- }
1136
- return false;
1137
- }
1138
-
1139
- private updImgRatioForActObj(): void {
1140
- const parent: ImageEditor = this.parent;
1141
- const destPoints: ActivePoint = {startX: parent.img.destLeft, startY: parent.img.destTop,
1142
- width: parent.img.destWidth, height: parent.img.destHeight};
1143
- this.straightenShapes();
1144
- const { destLeft, destTop, destWidth, destHeight } = parent.img;
1145
- const activePoint: ActivePoint = parent.activeObj.activePoint;
1146
- parent.activeObj.imageRatio = { startX: ((activePoint.startX - destLeft) /
1147
- destWidth), startY: ((activePoint.startY - destTop) / destHeight),
1148
- endX: ((activePoint.endX - destLeft) / destWidth),
1149
- endY: ((activePoint.endY - destTop) / destHeight),
1150
- width: destWidth / activePoint.width, height: destHeight / activePoint.height };
1151
- if (parent.activeObj.rotationCirclePointColl) {
1152
- parent.activeObj.rotationCirclePointColl.ratioX = (parent.activeObj.rotationCirclePointColl.x -
1153
- destLeft) / destWidth;
1154
- parent.activeObj.rotationCirclePointColl.ratioY = (parent.activeObj.rotationCirclePointColl.y -
1155
- destTop) / destHeight;
1156
- }
1157
- if (parent.activeObj.shape === 'path') {this.updatePathRatio(parent.activeObj); }
1158
- else if (parent.activeObj.shape === 'arrow') {this.updateArrowRatio(parent.activeObj); }
1159
- parent.img.destLeft = destPoints.startX; parent.img.destTop = destPoints.startY;
1160
- parent.img.destWidth = destPoints.width; parent.img.destHeight = destPoints.height;
1161
- }
1162
-
1163
- private zoomObjColl(preventApply?: boolean): void {
1164
- const parent: ImageEditor = this.parent;
1165
- const destPoints: ActivePoint = {startX: parent.img.destLeft, startY: parent.img.destTop,
1166
- width: parent.img.destWidth, height: parent.img.destHeight};
1167
- this.straightenShapes();
1168
- if (parent.objColl.length > 0) {
1169
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1170
- let currObj: SelectionPoint = parent.objColl[i as number];
1171
- if (currObj.imageRatio) {
1172
- currObj.activePoint.startX = (currObj.imageRatio.startX * parent.img.destWidth) + parent.img.destLeft;
1173
- currObj.activePoint.startY = (currObj.imageRatio.startY * parent.img.destHeight) + parent.img.destTop;
1174
- currObj.activePoint.endX = (currObj.imageRatio.endX * parent.img.destWidth) + parent.img.destLeft;
1175
- currObj.activePoint.endY = (currObj.imageRatio.endY * parent.img.destHeight) + parent.img.destTop;
1176
- }
1177
- currObj = this.updateWidthHeight(currObj);
1178
- if (currObj.shape === 'text') {
1179
- this.updateFontSize(currObj);
1180
- } else if (currObj.shape === 'line' || currObj.shape === 'arrow') {
1181
- currObj.pointColl = this.getLinePoints(currObj.activePoint.startX, currObj.activePoint.startY, currObj.activePoint.endX,
1182
- currObj.activePoint.endY);
1183
- for (let n: number = 0, len: number = currObj.pointColl.length; n < len; n++) {
1184
- currObj.pointColl[n as number].ratioX =
1185
- (currObj.pointColl[n as number].x - parent.img.destLeft) / parent.img.destWidth;
1186
- currObj.pointColl[n as number].ratioY =
1187
- (currObj.pointColl[n as number].y - parent.img.destTop) / parent.img.destHeight;
1188
- }
1189
- if (currObj.shape === 'arrow') {
1190
- this.updateArrowSize(currObj);
1191
- }
1192
- if (parent.transform.straighten !== 0 && (currObj.shape === 'line' || currObj.shape === 'arrow')) {
1193
- this.straightenShapePoints(currObj);
1194
- }
1195
- } else if (currObj.shape === 'path') {
1196
- for (let l: number = 0, len: number = currObj.pointColl.length; l < len; l++) {
1197
- currObj.pointColl[l as number].x = (currObj.pointColl[l as number].ratioX * parent.img.destWidth) +
1198
- parent.img.destLeft;
1199
- currObj.pointColl[l as number].y = (currObj.pointColl[l as number].ratioY * parent.img.destHeight) +
1200
- parent.img.destTop;
1201
- }
1202
- this.updatePathRatio(currObj);
1203
- if (parent.transform.straighten !== 0) {
1204
- this.straightenPath(currObj);
1205
- }
1206
- }
1207
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint: currObj.activePoint,
1208
- obj: currObj}});
1209
- if (currObj.shape !== 'line' && currObj.shape !== 'arrow' && currObj.shape !== 'path' && currObj.rotatedAngle !== 0) {
1210
- this.setPointCollForShapeRotation(currObj);
1211
- currObj.rotationCirclePoint.x =
1212
- (currObj.rotationCirclePoint.ratioX * parent.img.destWidth) + parent.img.destLeft;
1213
- currObj.rotationCirclePoint.y =
1214
- (currObj.rotationCirclePoint.ratioY * parent.img.destHeight) + parent.img.destTop;
1215
- if (currObj.rotationCirclePointColl) {
1216
- currObj.rotationCirclePointColl.x =
1217
- (currObj.rotationCirclePointColl.ratioX * parent.img.destWidth) + parent.img.destLeft;
1218
- currObj.rotationCirclePointColl.y =
1219
- (currObj.rotationCirclePointColl.ratioY * parent.img.destHeight) + parent.img.destTop;
1220
- }
1221
- }
1222
- }
1223
- if (isNullOrUndefined(preventApply)) {
1224
- const temp: string = this.lowerContext.filter; this.lowerContext.filter = 'none';
1225
- this.iterateObjColl();
1226
- this.lowerContext.filter = temp;
1227
- }
1228
- }
1229
- parent.img.destLeft = destPoints.startX; parent.img.destTop = destPoints.startY;
1230
- parent.img.destWidth = destPoints.width; parent.img.destHeight = destPoints.height;
1231
- }
1232
-
1233
- private straightenPath(obj: SelectionPoint): void {
1234
- let point: Point;
1235
- for (let j: number = 0, len: number = obj.pointColl.length; j < len; j++) {
1236
- point = this.straightenPoints(obj.pointColl[j as number].x, obj.pointColl[j as number].y);
1237
- obj.pointColl[j as number].x = point.x;
1238
- obj.pointColl[j as number].y = point.y;
1239
- }
1240
- }
1241
-
1242
- private straightenFHD(): void {
1243
- const parent: ImageEditor = this.parent;
1244
- for (let i: number = 0, fLen: number = parent.freehandCounter; i < fLen; i++) {
1245
- parent.points = extend([], parent.pointColl[i as number].points, []) as Point[];
1246
- const len: number = parent.points.length; let point: Point;
1247
- for (let l: number = 0; l < len; l++) {
1248
- point = this.straightenPoints(parent.points[l as number].x, parent.points[l as number].y);
1249
- parent.points[l as number].x = point.x; parent.points[l as number].y = point.y;
1250
- }
1251
- }
1252
- const selPointCollObj: Object = {selPointColl: null };
1253
- parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false, value: {obj: selPointCollObj }});
1254
- for (let i: number = 0, fLen: number = parent.freehandCounter; i < fLen; i++) {
1255
- if (selPointCollObj['selPointColl'][i as number] && selPointCollObj['selPointColl'][i as number].points) {
1256
- const len: number = selPointCollObj['selPointColl'][i as number].points.length; let point: Point;
1257
- for (let l: number = 0; l < len; l++) {
1258
- point = this.straightenPoints(selPointCollObj['selPointColl'][i as number].points[l as number].x,
1259
- selPointCollObj['selPointColl'][i as number].points[l as number].y);
1260
- selPointCollObj['selPointColl'][i as number].points[l as number].x = point.x;
1261
- selPointCollObj['selPointColl'][i as number].points[l as number].y = point.y;
1262
- }
1263
- }
1264
- }
1265
- const straightenObj: Object = { straightenPoint: null };
1266
- parent.notify('freehand-draw', { prop: 'getStraightenPoint', onPropertyChange: false, value: {obj: straightenObj }});
1267
- if (straightenObj['straightenPoint']['x'] && straightenObj['straightenPoint']['y']) {
1268
- const obj: Object = {angle: 0 };
1269
- parent.notify('freehand-draw', { prop: 'getStraightenPointAngle', onPropertyChange: false, value: {obj: obj }});
1270
- const angle: number = (((parent.transform.straighten === 360 ? 0 : parent.transform.straighten) - obj['angle']) * (Math.PI / 180));
1271
- const point: Point = this.straightenPoints(straightenObj['straightenPoint']['x'], straightenObj['straightenPoint']['y'], angle);
1272
- if (angle === 0) {
1273
- point.x = straightenObj['straightenPoint']['x']; point.y = straightenObj['straightenPoint']['y'];
1274
- }
1275
- parent.notify('freehand-draw', { prop: 'setStraightenPoint', onPropertyChange: false, value: {x: point.x, y: point.y }});
1276
- }
1277
- }
1278
-
1279
- private straightenPoints(x: number, y: number, angle?: number): Point {
1280
- const parent: ImageEditor = this.parent;
1281
- const center: Point = {x: parent.img.destLeft + (parent.img.destWidth / 2), y: parent.img.destTop + (parent.img.destHeight / 2)};
1282
- angle = angle ? angle : ((parent.transform.straighten) * (Math.PI / 180));
1283
- const point: Point = { x: Math.cos(angle) * (x - center.x) - Math.sin(angle) * (y - center.y) + center.x,
1284
- y: Math.sin(angle) * (x - center.x) + Math.cos(angle) * (y - center.y) + center.y };
1285
- return point;
1286
- }
1287
-
1288
- private straightenShapes(): void {
1289
- const parent: ImageEditor = this.parent;
1290
- const { destLeft, destTop, destWidth, destHeight } = parent.img;
1291
- const straightenObj: Object = {bool: parent.isStraightening };
1292
- if (!straightenObj['bool'] || parent.transform.straighten === 0) {
1293
- return;
1294
- }
1295
- parent.notify('draw', {prop: 'updateImgCanvasPoints'});
1296
- const object: Object = {points: null };
1297
- parent.notify('draw', {prop: 'getImageCanvasPoints', value: {obj: object }});
1298
- const center: Point = {x: destLeft + (destWidth / 2), y: destTop + (destHeight / 2)};
1299
- const angle: number = -((parent.transform.straighten) * (Math.PI / 180));
1300
- const p1: Point = { x: Math.cos(angle) * (object['points'][0]['x'] - center.x) - Math.sin(angle) *
1301
- (object['points'][0]['y'] - center.y) + center.x,
1302
- y: Math.sin(angle) * (object['points'][0]['x'] - center.x) + Math.cos(angle) *
1303
- (object['points'][0]['y'] - center.y) + center.y };
1304
- const p2: Point = { x: Math.cos(angle) * (object['points'][1]['x'] - center.x) - Math.sin(angle) *
1305
- (object['points'][1]['y'] - center.y) + center.x,
1306
- y: Math.sin(angle) * (object['points'][1]['x'] - center.x) + Math.cos(angle) * (object['points'][1]['y']
1307
- - center.y) + center.y };
1308
- const p3: Point = { x: Math.cos(angle) * (object['points'][2]['x'] - center.x) - Math.sin(angle) *
1309
- (object['points'][2]['y'] - center.y) + center.x,
1310
- y: Math.sin(angle) * (object['points'][2]['x'] - center.x) + Math.cos(angle) * (object['points'][2]['y']
1311
- - center.y) + center.y };
1312
- parent.img.destWidth = p2.x - p1.x; parent.img.destHeight = p3.y - p2.y;
1313
- parent.img.destLeft = p1.x; parent.img.destTop = p1.y;
1314
- }
1315
-
1316
- private straightenShapePoints(obj: SelectionPoint, isReverse?: boolean): void {
1317
- const parent: ImageEditor = this.parent;
1318
- const { destLeft, destTop, destWidth, destHeight } = parent.img;
1319
- const straightenObj: Object = {bool: parent.isStraightening };
1320
- if (!straightenObj['bool']) {
1321
- return;
1322
- }
1323
- if (obj.shape === 'line' || obj.shape === 'arrow') {
1324
- obj.activePoint.width = obj.activePoint.endX > obj.activePoint.startX ? obj.activePoint.endX -
1325
- obj.activePoint.startX : obj.activePoint.startX - obj.activePoint.endX;
1326
- obj.activePoint.height = obj.activePoint.endY > obj.activePoint.startY ? obj.activePoint.endY -
1327
- obj.activePoint.startY : obj.activePoint.startY - obj.activePoint.endY;
1328
- const center: Point = {x: destLeft + (destWidth / 2), y: destTop + (destHeight / 2)};
1329
- const angle: number = (isReverse ? -parent.transform.straighten : parent.transform.straighten) * (Math.PI / 180);
1330
- const start: Point = { x: Math.cos(angle) * (obj.activePoint.startX - center.x) - Math.sin(angle) *
1331
- (obj.activePoint.startY - center.y) + center.x, y: Math.sin(angle) * (obj.activePoint.startX - center.x) + Math.cos(angle)
1332
- * (obj.activePoint.startY - center.y) + center.y };
1333
- const end: Point = { x: Math.cos(angle) * (obj.activePoint.endX - center.x) -
1334
- Math.sin(angle) * (obj.activePoint.endY - center.y) + center.x, y: Math.sin(angle) * (obj.activePoint.endX - center.x) +
1335
- Math.cos(angle) * (obj.activePoint.endY - center.y) + center.y };
1336
- obj.activePoint.startX = start.x; obj.activePoint.startY = start.y;
1337
- obj.activePoint.endX = end.x; obj.activePoint.endY = end.y;
1338
- obj.activePoint.width = obj.activePoint.endX > obj.activePoint.startX ? obj.activePoint.endX -
1339
- obj.activePoint.startX : obj.activePoint.startX - obj.activePoint.endX;
1340
- obj.activePoint.height = obj.activePoint.endY > obj.activePoint.startY ? obj.activePoint.endY -
1341
- obj.activePoint.startY : obj.activePoint.startY - obj.activePoint.endY;
1342
- parent.notify('selection', { prop: 'adjustActObjForLineArrow', onPropertyChange: false, value: {obj: obj }});
1343
- }
1344
- }
1345
-
1346
- private redrawObj(degree?: number | string): void {
1347
- const parent: ImageEditor = this.parent;
1348
- let isShape: boolean = false;
1349
- if (parent.objColl.length > 0) {
1350
- if (degree === 'horizontal' || degree === 'vertical' || degree === 'Horizontal' || degree === 'Vertical' ||
1351
- degree === 'horizontalVertical' || degree === 'verticalHorizontal') {
1352
- this.updateCurrentActiveObjPoint((degree as string).toLowerCase());
1353
- } else if (typeof(degree) === 'number') {
1354
- this.updateCurrentActiveObjPoint(degree); const tempFilter: string = this.lowerContext.filter;
1355
- this.lowerContext.filter = 'brightness(' + 1 + ') ' + 'contrast(' + 100 + '%) ' + 'hue-rotate(' + 0 + 'deg) ' +
1356
- 'saturate(' + 100 + '%) ' + 'opacity(' + 1 + ') ' + 'blur(' + 0 + 'px) ' + 'sepia(0%) ' + 'grayscale(0%) ' + 'invert(0%)';
1357
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1358
- const splitWords: string[] = parent.objColl[i as number].shape.split('-');
1359
- if (splitWords[0] !== 'crop') {
1360
- this.apply(parent.objColl[i as number].shape, parent.objColl[i as number]);
1361
- isShape = true;
1362
- }
1363
- }
1364
- if (isShape) {
1365
- parent.notify('draw', {prop: 'applyFrame', value: {ctx: this.lowerContext, frame: parent.frameObj.type, preventImg: true}});
1366
- }
1367
- this.lowerContext.filter = tempFilter;
1368
- }
1369
- }
1370
- }
1371
-
1372
- private updateCurrentActiveObjPoint(degree: number | string): void {
1373
- const parent: ImageEditor = this.parent;
1374
- let currActObjIndex: number; const { destLeft, destTop, destWidth, destHeight } = parent.img;
1375
- for (let index: number = 0, len: number = parent.objColl.length; index < len; index++) {
1376
- const currObj: SelectionPoint = parent.objColl[index as number];
1377
- if (parent.activeObj.shape === currObj.shape &&
1378
- parent.activeObj.activePoint.startX === currObj.activePoint.startX &&
1379
- parent.activeObj.activePoint.startY === currObj.activePoint.startY &&
1380
- parent.activeObj.activePoint.endX === currObj.activePoint.endX &&
1381
- parent.activeObj.activePoint.endY === currObj.activePoint.endY &&
1382
- parent.activeObj.currIndex === currObj.currIndex) {
1383
- currActObjIndex = index;
1384
- break;
1385
- }
1386
- }
1387
- if (degree === 'horizontal' || degree === 'vertical' || degree === 'Horizontal' || degree === 'Vertical' ||
1388
- degree === 'horizontalvertical' || degree === 'verticalhorizontal') {
1389
- if (degree === 'horizontal' || degree === 'Horizontal') {
1390
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1391
- const currObj: SelectionPoint = parent.objColl[i as number];
1392
- if (currObj.shapeFlip !== parent.transform.currFlipState) {
1393
- if (currObj.activePoint.startX <= destLeft + (destWidth / 2)) {
1394
- currObj.activePoint.endX = (destLeft + destWidth) - (currObj.activePoint.startX - destLeft);
1395
- currObj.activePoint.startX = currObj.activePoint.endX - currObj.activePoint.width;
1396
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint:
1397
- currObj.activePoint, obj: currObj}});
1398
- } else if (currObj.activePoint.startX >= destLeft + (destWidth / 2)) {
1399
- currObj.activePoint.startX = destLeft + (destLeft + destWidth - currObj.activePoint.endX);
1400
- currObj.activePoint.endX = currObj.activePoint.startX + currObj.activePoint.width;
1401
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value:
1402
- {actPoint: currObj.activePoint, obj: currObj}});
1403
- }
1404
- if (currObj.shape === 'line' || currObj.shape === 'arrow' || currObj.shape === 'path') {
1405
- this.flipLineArrowObj(currObj, 'horizontal');
1406
- } else if (currObj.rotatedAngle !== 0) {
1407
- currObj.rotatedAngle = currObj.rotatedAngle + (Math.PI - currObj.rotatedAngle) * 2;
1408
- if (currObj.rotationCirclePointColl.x <= destLeft + (destWidth / 2)) {
1409
- currObj.rotationCirclePointColl.x = (destLeft + destWidth) -
1410
- (currObj.rotationCirclePointColl.x - destLeft);
1411
- } else if (currObj.rotationCirclePointColl.x >= destLeft + (destWidth / 2)) {
1412
- currObj.rotationCirclePointColl.x = destLeft +
1413
- (destLeft + destWidth - currObj.rotationCirclePointColl.x);
1414
- }
1415
- currObj.rotationCirclePointColl.ratioX =
1416
- (currObj.rotationCirclePointColl.x - destLeft) / destWidth;
1417
- }
1418
- currObj.shapeFlip = parent.transform.currFlipState;
1419
- currObj.imageRatio = {startX: ((currObj.activePoint.startX - destLeft) / destWidth),
1420
- startY: ((currObj.activePoint.startY - destTop) / destHeight),
1421
- endX: ((currObj.activePoint.endX - destLeft) / destWidth),
1422
- endY: ((currObj.activePoint.endY - destTop) / destHeight),
1423
- width: destWidth / currObj.activePoint.width,
1424
- height: destHeight / currObj.activePoint.height };
1425
- }
1426
- }
1427
- }
1428
- else if (degree === 'vertical' || degree === 'Vertical') {
1429
- for (let i: number = 0; i < parent.objColl.length; i++) {
1430
- const currObj: SelectionPoint = parent.objColl[i as number];
1431
- if (currObj.shapeFlip !== parent.transform.currFlipState) {
1432
- if (currObj.activePoint.startY <= destTop + (destHeight / 2)) {
1433
- currObj.activePoint.endY = (destTop + destHeight) - (currObj.activePoint.startY - destTop);
1434
- currObj.activePoint.startY = currObj.activePoint.endY - currObj.activePoint.height;
1435
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint: currObj.activePoint,
1436
- obj: currObj}});
1437
- } else if (currObj.activePoint.startY >= parent.lowerCanvas.height / 2) {
1438
- currObj.activePoint.startY = destTop + (destTop + destHeight - currObj.activePoint.endY);
1439
- currObj.activePoint.endY = currObj.activePoint.startY + currObj.activePoint.height;
1440
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint: currObj.activePoint,
1441
- obj: currObj}});
1442
- }
1443
- if (currObj.shape === 'line' || currObj.shape === 'arrow' ||
1444
- currObj.shape === 'path') {
1445
- this.flipLineArrowObj(currObj, 'vertical');
1446
- } else if (currObj.rotatedAngle !== 0) {
1447
- currObj.rotatedAngle = -currObj.rotatedAngle;
1448
- if (currObj.rotationCirclePointColl.y <= destTop + (destHeight / 2)) {
1449
- currObj.rotationCirclePointColl.y = (destTop + destHeight) - (currObj.rotationCirclePointColl.y - destTop);
1450
- } else if (currObj.rotationCirclePointColl.y >= destTop +
1451
- (destHeight / 2)) {
1452
- currObj.rotationCirclePointColl.y = destTop + (destTop + destHeight - currObj.rotationCirclePointColl.y);
1453
- }
1454
- currObj.rotationCirclePointColl.ratioY =
1455
- (currObj.rotationCirclePointColl.y - destTop) / destHeight;
1456
- }
1457
- currObj.shapeFlip = parent.transform.currFlipState;
1458
- currObj.imageRatio = {startX: ((currObj.activePoint.startX - destLeft) / destWidth),
1459
- startY: ((currObj.activePoint.startY - destTop) / destHeight),
1460
- endX: ((currObj.activePoint.endX - destLeft) / destWidth),
1461
- endY: ((currObj.activePoint.endY - destTop) / destHeight),
1462
- width: destWidth / currObj.activePoint.width,
1463
- height: destHeight / currObj.activePoint.height };
1464
- }
1465
- }
1466
- }
1467
- else if (degree === 'verticalhorizontal' || degree === 'horizontalvertical') {
1468
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1469
- const currObj: SelectionPoint = parent.objColl[i as number];
1470
- if (currObj.shapeFlip !== parent.transform.currFlipState) {
1471
- if (currObj.activePoint.startX <= destLeft + (destWidth / 2)) {
1472
- currObj.activePoint.endX = (destLeft + destWidth) - (currObj.activePoint.startX -
1473
- destLeft);
1474
- currObj.activePoint.startX = currObj.activePoint.endX - currObj.activePoint.width;
1475
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value:
1476
- {actPoint: currObj.activePoint, obj: currObj}});
1477
- } else if (currObj.activePoint.startX >= destLeft + (destWidth / 2)) {
1478
- currObj.activePoint.startX = destLeft + (destLeft +
1479
- destWidth - currObj.activePoint.endX);
1480
- currObj.activePoint.endX = currObj.activePoint.startX + currObj.activePoint.width;
1481
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint:
1482
- currObj.activePoint, obj: currObj}});
1483
- }
1484
- if (currObj.activePoint.startY <= destTop + (destHeight / 2)) {
1485
- currObj.activePoint.endY = (destTop + destHeight) -
1486
- (currObj.activePoint.startY - destTop);
1487
- currObj.activePoint.startY = currObj.activePoint.endY -
1488
- currObj.activePoint.height;
1489
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint:
1490
- currObj.activePoint, obj: currObj}});
1491
- } else if (currObj.activePoint.startY >= parent.lowerCanvas.height / 2) {
1492
- currObj.activePoint.startY = destTop + (destTop +
1493
- destHeight - currObj.activePoint.endY);
1494
- currObj.activePoint.endY = currObj.activePoint.startY +
1495
- currObj.activePoint.height;
1496
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value:
1497
- {actPoint: currObj.activePoint, obj: currObj}});
1498
- }
1499
- if (currObj.shape === 'line' || currObj.shape === 'arrow' || currObj.shape === 'path') {
1500
- this.flipLineArrowObj(currObj, degree);
1501
- }
1502
- currObj.shapeFlip = parent.transform.currFlipState;
1503
- currObj.imageRatio = {startX: ((currObj.activePoint.startX - destLeft) / destWidth),
1504
- startY: ((currObj.activePoint.startY - destTop) / destHeight),
1505
- endX: ((currObj.activePoint.endX - destLeft) / destWidth),
1506
- endY: ((currObj.activePoint.endY - destTop) / destHeight),
1507
- width: destWidth / currObj.activePoint.width,
1508
- height: destHeight / currObj.activePoint.height };
1509
- }
1510
- }
1511
- }
1512
- if (currActObjIndex !== undefined) {
1513
- parent.activeObj = extend({}, parent.objColl[currActObjIndex as number], {}, true) as SelectionPoint;
1514
- }
1515
- }
1516
- else if (degree === 90) {
1517
- this.rotateObjColl();
1518
- }
1519
- else if (degree === -90) {
1520
- for (let i: number = 0; i < 3; i++) {
1521
- this.rotateObjColl();
1522
- }
1523
- } else if (typeof(degree) === 'number') {
1524
- if (degree > 0) {this.rotateObjColl(); }
1525
- else {
1526
- for (let i: number = 0; i < 3; i++) {
1527
- this.rotateObjColl();
1528
- }
1529
- }
1530
- }
1531
- }
1532
-
1533
- private rotateObjColl(): void {
1534
- const parent: ImageEditor = this.parent;
1535
- const { destWidth, destHeight, destLeft, destTop } = parent.img;
1536
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1537
- let currObj: SelectionPoint = parent.objColl[i as number];
1538
- const shape: string = currObj.shape;
1539
- currObj.activePoint.startY = destTop + (destHeight * currObj.imageRatio.startX);
1540
- currObj.activePoint.endY = destTop + (destHeight * currObj.imageRatio.endX);
1541
- currObj.activePoint.startX = (destLeft + destWidth) - (destWidth * currObj.imageRatio.endY);
1542
- currObj.activePoint.endX = (destLeft + destWidth) - (destWidth * currObj.imageRatio.startY);
1543
- currObj = this.updateWidthHeight(parent.objColl[i as number]);
1544
- this.updateFontSize(currObj);
1545
- if (shape === 'line' || shape === 'arrow' || shape === 'path') {
1546
- this.rotateLineArrowObj(currObj);
1547
- if (shape === 'arrow') {
1548
- this.updateArrowSize(currObj);
1549
- }
1550
- } else if (currObj.rotatedAngle !== 0) {
1551
- currObj.rotationCirclePointColl.y = destTop + (destHeight * currObj.rotationCirclePointColl.ratioX);
1552
- currObj.rotationCirclePointColl.x = (destLeft + destWidth) -
1553
- (destWidth * currObj.rotationCirclePointColl.ratioY);
1554
- currObj.rotationCirclePointColl.ratioX = (currObj.rotationCirclePointColl.x - destLeft) / destWidth;
1555
- currObj.rotationCirclePointColl.ratioY = (currObj.rotationCirclePointColl.y - destTop) / destHeight;
1556
- }
1557
- }
1558
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1559
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint:
1560
- parent.objColl[i as number].activePoint, obj: parent.objColl[i as number]}});
1561
- }
1562
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1563
- const currObj: SelectionPoint = parent.objColl[i as number];
1564
- currObj.imageRatio = {startX: ((currObj.activePoint.startX - destLeft) / destWidth),
1565
- startY: ((currObj.activePoint.startY - destTop) / destHeight),
1566
- endX: ((currObj.activePoint.endX - destLeft) / destWidth),
1567
- endY: ((currObj.activePoint.endY - destTop) / destHeight),
1568
- width: destWidth / currObj.activePoint.width,
1569
- height: destHeight / currObj.activePoint.height };
1570
- }
1571
- }
1572
-
1573
- private rotateLineArrowObj(obj: SelectionPoint): void {
1574
- if (isNullOrUndefined(obj.pointColl)) {
1575
- return;
1576
- }
1577
- const parent: ImageEditor = this.parent;
1578
- const { destWidth, destHeight, destLeft, destTop } = parent.img;
1579
- if (obj.pointColl.length > 0) {
1580
- for (let n: number = 0; n < obj.pointColl.length; n++) {
1581
- obj.pointColl[n as number].y = destTop + (destHeight * obj.pointColl[n as number].ratioX);
1582
- obj.pointColl[n as number].x = (destLeft + destWidth) - (destWidth *
1583
- obj.pointColl[n as number].ratioY);
1584
- }
1585
- for (let n: number = 0; n < obj.pointColl.length; n++) {
1586
- obj.pointColl[n as number].ratioX = (obj.pointColl[n as number].x - destLeft) / destWidth;
1587
- obj.pointColl[n as number].ratioY = (obj.pointColl[n as number].y - destTop) / destHeight;
1588
- }
1589
- let prevPoint: Point;
1590
- if (isNullOrUndefined(obj.pointColl[obj.pointColl.length - 2])) {prevPoint = {x: 0, y: 0 }; }
1591
- else {prevPoint = {x: obj.pointColl[obj.pointColl.length - 2].x, y: obj.pointColl[obj.pointColl.length - 2].y }; }
1592
- const diffX: number = obj.pointColl[obj.pointColl.length - 1].x - prevPoint.x;
1593
- const diffY: number = obj.pointColl[obj.pointColl.length - 1].y - prevPoint.y;
1594
- obj.activePoint.startX = obj.pointColl[0].x; obj.activePoint.startY = obj.pointColl[0].y;
1595
- obj.activePoint.endX = obj.pointColl[obj.pointColl.length - 1].x + (diffX / 2);
1596
- obj.activePoint.endY = obj.pointColl[obj.pointColl.length - 1].y + (diffY / 2);
1597
- obj = this.updateWidthHeight(obj);
1598
- }
1599
- }
1600
-
1601
- private flipLineArrowObj(obj: SelectionPoint, value: string): void {
1602
- value = value.toLowerCase();
1603
- if (isNullOrUndefined(obj.pointColl)) {return; }
1604
- if (value === 'horizontal') {this.lineArrowHorizontalFlip(obj); }
1605
- else if (value === 'vertical') {this.lineArrowVerticalFlip(obj); }
1606
- else {this.lineArrowHorizontalFlip(obj); obj.shapeFlip = ''; this.lineArrowVerticalFlip(obj); }
1607
- obj.activePoint.startX = obj.pointColl[0].x; obj.activePoint.startY = obj.pointColl[0].y;
1608
- obj.activePoint.endX = obj.pointColl[obj.pointColl.length - 1].x;
1609
- obj.activePoint.endY = obj.pointColl[obj.pointColl.length - 1].y;
1610
- if (obj.activePoint.startX > obj.activePoint.endX) {
1611
- let temp: number = obj.activePoint.startX; obj.activePoint.startX = obj.activePoint.endX;
1612
- obj.activePoint.endX = temp; temp = obj.activePoint.startY;
1613
- obj.activePoint.startY = obj.activePoint.endY; obj.activePoint.endY = temp;
1614
- }
1615
- }
1616
-
1617
- private lineArrowHorizontalFlip(obj: SelectionPoint): void {
1618
- const parent: ImageEditor = this.parent;
1619
- const { destWidth, destHeight, destLeft, destTop } = parent.img;
1620
- if (obj.shapeFlip !== parent.transform.currFlipState) {
1621
- for (let l: number = 0, len: number = obj.pointColl.length; l < len; l++) {
1622
- const currPoint: Point = obj.pointColl[l as number];
1623
- if (currPoint.x <= destLeft + (destWidth / 2)) {
1624
- currPoint.x = (destLeft + destWidth) - (currPoint.x - destLeft);
1625
- } else if (currPoint.x >= destLeft + (destWidth / 2)) {
1626
- currPoint.x = destLeft + (destLeft + destWidth - currPoint.x);
1627
- }
1628
- currPoint.ratioX = (currPoint.x - destLeft) / destWidth;
1629
- currPoint.ratioY = (currPoint.y - destTop) / destHeight;
1630
- }
1631
- if (obj.shape === 'arrow') {
1632
- const value: string = obj.start; obj.start = obj.end; obj.end = value;
1633
- }
1634
- obj.shapeFlip = parent.transform.currFlipState;
1635
- }
1636
- }
1637
-
1638
- private lineArrowVerticalFlip(obj: SelectionPoint): void {
1639
- const parent: ImageEditor = this.parent;
1640
- const { destWidth, destHeight, destLeft, destTop } = parent.img;
1641
- if (obj.shapeFlip !== parent.transform.currFlipState) {
1642
- for (let l: number = 0, len: number = obj.pointColl.length; l < len; l++) {
1643
- const currPoint: Point = obj.pointColl[l as number];
1644
- if (currPoint.y <= destTop + (destHeight / 2)) {
1645
- currPoint.y = (destTop + destHeight) - (currPoint.y - destTop);
1646
- } else if (currPoint.y >= destTop + (destHeight / 2)) {
1647
- currPoint.y = destTop + (destTop + destHeight - currPoint.y);
1648
- }
1649
- currPoint.ratioX = (currPoint.x - destLeft) / destWidth;
1650
- currPoint.ratioY = (currPoint.y - destTop) / destHeight;
1651
- }
1652
- obj.shapeFlip = parent.transform.currFlipState;
1653
- }
1654
- }
1655
-
1656
- private getRotDegOfShape(obj: SelectionPoint, value?: boolean): number {
1657
- const parent: ImageEditor = this.parent;
1658
- let degree: number;
1659
- if (obj.shapeDegree === 0) {degree = this.parent.transform.degree; }
1660
- else {degree = this.parent.transform.degree - obj.shapeDegree; }
1661
- if (degree < 0) {degree = 360 + degree; }
1662
- const transformObj: Object = {bool: false };
1663
- parent.notify('selection', { prop: 'getTransformedShape', onPropertyChange: false, value: {obj: transformObj}});
1664
- if (transformObj['bool'] && !value && parent.activeObj.rotateFlipColl) {
1665
- degree = 0;
1666
- for (let i: number = 0; i < parent.activeObj.rotateFlipColl.length; i++) {
1667
- if (typeof(parent.activeObj.rotateFlipColl[i as number]) === 'number') {
1668
- degree += (parent.activeObj.rotateFlipColl[i as number]);
1669
- }
1670
- }
1671
- }
1672
- return degree;
1673
- }
1674
-
1675
- private renderTextArea(x: number, y: number, actObj: SelectionPoint): void {
1676
- const parent: ImageEditor = this.parent;
1677
- const shapeObj: Object = {shapeSettingsObj: {} as ShapeSettings };
1678
- parent.notify('selection', { prop: 'updatePrevShapeSettings', onPropertyChange: false, value: {obj: shapeObj}});
1679
- const shapeSettings: ShapeSettings = shapeObj['shapeSettingsObj'];
1680
- const shapeChangingArgs: ShapeChangeEventArgs = {cancel: false, action: 'text-edit', previousShapeSettings: shapeSettings,
1681
- currentShapeSettings: shapeSettings};
1682
- parent.trigger('shapeChanging', shapeChangingArgs);
1683
- this.updateShapeChangeEventArgs(shapeChangingArgs.currentShapeSettings, shapeChangingArgs.allowShapeOverflow);
1684
- const degree: number = this.getRotDegOfShape(parent.activeObj);
1685
- this.transformTextArea();
1686
- parent.notify('toolbar', { prop: 'destroy-qa-toolbar', onPropertyChange: false});
1687
- const zOrderElem: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_zOrderBtn');
1688
- const dupElem: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_duplicate');
1689
- const removeElem: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_remove');
1690
- const editTextElem: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_editText');
1691
- const shadowColor: string = actObj.strokeSettings.outlineColor;
1692
- const outlineWidth: number = actObj.strokeSettings.outlineWidth;
1693
- const shadows: string[] = [];
1694
- if (zOrderElem) {zOrderElem.classList.add('e-overlay'); }
1695
- if (dupElem) {dupElem.classList.add('e-overlay'); }
1696
- if (removeElem) {removeElem.classList.add('e-overlay'); }
1697
- if (editTextElem) {editTextElem.classList.add('e-overlay'); }
1698
- if (actObj.strokeSettings.fillColor !== '') {
1699
- parent.textArea.style.backgroundColor = actObj.strokeSettings.fillColor;
1700
- } else {
1701
- parent.textArea.style.backgroundColor = 'transparent';
1702
- }
1703
- parent.textArea.style.display = 'block'; parent.textArea.style.left = x + 'px';
1704
- parent.textArea.style.top = y + 'px'; parent.textArea.style.fontFamily = actObj.textSettings.fontFamily;
1705
- parent.textArea.style.fontSize = actObj.textSettings.fontSize + 'px';
1706
- parent.textArea.style.color = actObj.strokeSettings.strokeColor;
1707
- const fontSize: number = actObj.textSettings.fontSize;
1708
- const baseWidth: number = Math.max(1, outlineWidth / 2);
1709
- const adjustedOutlineWidth: number = baseWidth * (Math.floor((fontSize - 1) / 16) * 0.5 + 0.5);
1710
- if (/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$|^[a-zA-Z]+$/.test(actObj.strokeSettings.outlineColor)) {
1711
- for (let x: number = -adjustedOutlineWidth; x <= adjustedOutlineWidth; x++) {
1712
- for (let y: number = -adjustedOutlineWidth; y <= adjustedOutlineWidth; y++) {
1713
- if (x !== 0 || y !== 0) {
1714
- shadows.push(`${x / 2}px ${y / 2}px 0 ${shadowColor}`);
1715
- }
1716
- }
1717
- }
1718
- parent.textArea.style.textShadow = shadows.join(', ');
1719
- } else {
1720
- parent.textArea.style.textShadow = null;
1721
- }
1722
- parent.textArea.style.fontWeight = actObj.textSettings.bold ? 'bold' : 'normal';
1723
- parent.textArea.style.fontStyle = actObj.textSettings.italic ? 'italic' : 'normal';
1724
- parent.textArea.style.textDecoration = (actObj.textSettings.underline && actObj.textSettings.strikethrough) ? 'underline line-through' :
1725
- (actObj.textSettings.underline) ? 'underline' :
1726
- (actObj.textSettings.strikethrough) ? 'line-through' : 'none';
1727
- parent.textArea.style.border = '2px solid ' + parent.themeColl[parent.theme]['primaryColor'];
1728
- parent.textArea.value = actObj.keyHistory; parent.textArea.style.overflow = 'hidden';
1729
- parent.textArea.style.width = 'auto'; parent.textArea.style.height = 'auto';
1730
- parent.textArea.focus();
1731
- const { width, height } = actObj.activePoint;
1732
- if (degree % 90 === 0 && degree % 180 !== 0 && degree !== 0) {
1733
- parent.textArea.style.width = height + (height * 0.25) + 'px';
1734
- parent.textArea.style.height = width + (width * 0.25) + 'px';
1735
- } else {
1736
- parent.textArea.style.width = width + (width * 0.25) + 'px';
1737
- parent.textArea.style.height = height + (height * 0.25) + 'px';
1738
- }
1739
- this.setTextBoxWidth(); const obj: Object = {flipColl: null };
1740
- parent.notify('transform', { prop: 'getFlipColl', onPropertyChange: false, value: {obj: obj }});
1741
- if (obj['flipColl'].length <= 1) {this.setTextBoxHeight(); }
1742
- if (parseFloat(parent.textArea.style.maxHeight) < parent.activeObj.textSettings.fontSize) {
1743
- parent.textArea.style.maxHeight = parent.activeObj.textSettings.fontSize + 'px';
1744
- }
1745
- if (degree % 90 === 0 && degree % 180 !== 0) {
1746
- if (parseFloat(parent.textArea.style.left) + parseFloat(parent.textArea.style.width) > parent.img.destTop +
1747
- parent.img.destHeight) {this.alignTextAreaIntoCanvas(); }
1748
- } else {
1749
- if (parseFloat(parent.textArea.style.left) + parseFloat(parent.textArea.style.width) > parent.img.destLeft +
1750
- parent.img.destWidth) {this.alignTextAreaIntoCanvas(); }
1751
- }
1752
- // Limit text area
1753
- if (actObj.rotatedAngle !== 0) {
1754
- let tempLeft: number = parseFloat(parent.textArea.style.left); let tempTop: number = parseFloat(parent.textArea.style.top);
1755
- if (actObj.flipObjColl.length > 0) {
1756
- const panObj: Object = {panRegion: '' };
1757
- const { clientWidth, clientHeight } = parent.lowerCanvas;
1758
- let center: Point = {x: 0, y: 0};
1759
- parent.notify('crop', { prop: 'getCurrFlipState', onPropertyChange: false,
1760
- value: {panObj: panObj }});
1761
- if (panObj['panRegion'] !== '') {
1762
- if (panObj['panRegion'] === 'horizontal') {
1763
- center.x = clientWidth - (clientWidth / 2);
1764
- tempLeft = (center.x - tempLeft) + center.x;
1765
- } else if (panObj['panRegion'] === 'vertical') {
1766
- center.y = clientHeight - (clientHeight / 2);
1767
- tempTop = (center.y - tempTop) + center.y;
1768
- } else {
1769
- center = {x: clientWidth - (clientWidth / 2), y: clientHeight - (clientHeight / 2)};
1770
- tempLeft = (center.x - tempLeft) + center.x;
1771
- tempTop = (center.y - tempTop) + center.y;
1772
- }
1773
- }
1774
- }
1775
- let left: number = tempLeft + parseFloat(parent.textArea.style.width);
1776
- const top: number = tempTop + parseFloat(parent.textArea.style.height);
1777
- let width1: number = parseFloat(parent.textArea.style.width);
1778
- const height1: number = parseFloat(parent.textArea.style.height);
1779
- let center: Point = {x: left - (width1 / 2), y: top - (height1 / 2)};
1780
- const cosAngle: number = Math.cos(actObj.rotatedAngle);
1781
- const sinAngle: number = Math.sin(actObj.rotatedAngle);
1782
- let p1: Point = { x: cosAngle * (left - center.x) - sinAngle * (top - center.y) + center.x,
1783
- y: sinAngle * (left - center.x) + cosAngle * (top - center.y) + center.y };
1784
- if (p1.x > parent.img.destLeft && p1.x < parent.img.destLeft + parent.img.destWidth &&
1785
- // eslint-disable-next-line max-len
1786
- p1.y > parent.img.destTop && p1.y + parseFloat(parent.textArea.style.fontSize) < parent.img.destTop + parent.img.destHeight) {
1787
- // eslint-disable-next-line no-self-assign
1788
- parent.textArea.style.width = parent.textArea.style.width;
1789
- } else {
1790
- let count: number = 0;
1791
- const width2: number = parseFloat(parent.textArea.style.width);
1792
- while (true) {
1793
- count++;
1794
- width1 -= 1;
1795
- left = tempLeft + width1;
1796
- center = {x: left - (width1 / 2), y: top - (height1 / 2)};
1797
- p1 = { x: cosAngle * (left - center.x) - sinAngle * (top - center.y) + center.x,
1798
- y: sinAngle * (left - center.x) + cosAngle * (top - center.y) + center.y };
1799
- if ((p1.x > parent.img.destLeft && p1.x < parent.img.destLeft + parent.img.destWidth &&
1800
- // eslint-disable-next-line max-len
1801
- p1.y > parent.img.destTop && p1.y + parseFloat(parent.textArea.style.fontSize) < parent.img.destTop + parent.img.destHeight) ||
1802
- count === width2) {
1803
- parent.textArea.style.width = width1 + 'px';
1804
- break;
1805
- }
1806
- }
1807
- }
1808
- }
1809
- parent.notify('selection', { prop: 'clearUpperCanvas', onPropertyChange: false});
1810
- }
1811
-
1812
- private setTextBoxWidth(e?: KeyboardEvent): void {
1813
- const parent: ImageEditor = this.parent;
1814
- if (parent.activeObj.rotatedAngle !== 0) {
1815
- parent.textArea.style.whiteSpace = 'nowrap';
1816
- parent.textArea.style.textOverflow = 'ellipsis';
1817
- parent.textArea.style.display = 'inline-block';
1818
- return;
1819
- } else {
1820
- parent.textArea.style.whiteSpace = '';
1821
- parent.textArea.style.textOverflow = '';
1822
- if (parent.textArea.style.display === 'inline-block') {
1823
- parent.textArea.style.display = 'block';
1824
- }
1825
- }
1826
- const text: string = this.getMaxText(true);
1827
- if (parent.textArea.style.display === 'block' || parent.textArea.style.display === 'inline-block') {this.updateFontStyles(true); }
1828
- else {this.updateFontStyles(); }
1829
- const textAreaWidth: number = (this.upperContext.measureText(text).width + (parseFloat(parent.textArea.style.fontSize) / 2));
1830
- const letterWidth: number = e ? this.upperContext.measureText(String.fromCharCode(e.which)).width : 0;
1831
- const actObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
1832
- let flip: string = ''; const degree: number = this.getRotDegOfShape(actObj);
1833
- if (actObj.shapeFlip !== parent.transform.currFlipState) {flip = ''; }
1834
- else {flip = parent.transform.currFlipState; }
1835
- if ((e && parseFloat(parent.textArea.style.width) < (textAreaWidth + letterWidth)) || isNullOrUndefined(e)) {
1836
- if (degree === 0) {
1837
- if (flip.toLowerCase() === 'horizontal') {
1838
- if ((parseFloat(parent.textArea.style.left) - parent.img.destLeft) - textAreaWidth - letterWidth > 0) {
1839
- parent.textArea.style.width = (textAreaWidth + letterWidth) + 'px';
1840
- }
1841
- } else if ((parent.img.destWidth - (parseFloat(parent.textArea.style.left) -
1842
- parent.img.destLeft)) > (textAreaWidth + letterWidth)) {
1843
- parent.textArea.style.width = (textAreaWidth + letterWidth) + 'px';
1844
- }
1845
- } else if (degree === 90) {
1846
- if (flip.toLowerCase() === 'vertical') {
1847
- if ((parseFloat(parent.textArea.style.top) - parent.img.destTop) - textAreaWidth - letterWidth > 0) {
1848
- parent.textArea.style.width = (textAreaWidth + letterWidth) + 'px';
1849
- }
1850
- }
1851
- else if ((parent.img.destHeight - (parseFloat(parent.textArea.style.top) -
1852
- parent.img.destTop)) > (textAreaWidth + letterWidth)) {
1853
- parent.textArea.style.width = (textAreaWidth + letterWidth) + 'px';
1854
- }
1855
- } else if (degree === 180) {
1856
- const textAreaLeft: number = parseFloat(parent.textArea.style.left);
1857
- const destLeft: number = parent.img.destLeft;
1858
- if (flip.toLowerCase() === 'horizontal') {
1859
- const remainingWidth: number = parent.img.destWidth - (textAreaLeft - destLeft);
1860
- if (remainingWidth > textAreaWidth + letterWidth) {
1861
- parent.textArea.style.width = (textAreaWidth + letterWidth) + 'px';
1862
- }
1863
- } else {
1864
- const distanceToLeft: number = textAreaLeft - destLeft;
1865
- if (distanceToLeft - textAreaWidth - letterWidth > 0) {
1866
- parent.textArea.style.width = (textAreaWidth + letterWidth) + 'px';
1867
- }
1868
- }
1869
- } else if (degree === 270) {
1870
- const textAreaTop: number = parseFloat(parent.textArea.style.top);
1871
- const destTop: number = parent.img.destTop;
1872
- if (flip.toLowerCase() === 'vertical') {
1873
- const remainingHeight: number = parent.img.destHeight - (textAreaTop - destTop);
1874
- if (remainingHeight > textAreaWidth + letterWidth) {
1875
- parent.textArea.style.width = (textAreaWidth + letterWidth) + 'px';
1876
- }
1877
- } else {
1878
- const distanceToTop: number = textAreaTop - destTop;
1879
- if (distanceToTop - textAreaWidth - letterWidth > 0) {
1880
- parent.textArea.style.width = (textAreaWidth + letterWidth) + 'px';
1881
- }
1882
- }
1883
- }
1884
- }
1885
- }
1886
-
1887
- private setTextBoxHeight(): void {
1888
- const parent: ImageEditor = this.parent; let textAreaTop: number;
1889
- const actObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
1890
- let flip: string = ''; const degree: number = this.getRotDegOfShape(actObj);
1891
- if (actObj.textFlip === parent.transform.currFlipState) {
1892
- flip = '';
1893
- } else if (actObj.textFlip === '') {
1894
- flip = parent.transform.currFlipState;
1895
- } else {
1896
- flip = actObj.textFlip;
1897
- }
1898
- switch (degree) {
1899
- case 0:
1900
- if (flip.toLowerCase() === 'vertical') {
1901
- parent.textArea.style.maxHeight = (parent.img.destHeight - (parent.img.destHeight -
1902
- parseFloat(parent.textArea.style.top))) + 'px';
1903
- } else {
1904
- textAreaTop = parseFloat(parent.textArea.style.top) - parent.img.destTop;
1905
- parent.textArea.style.maxHeight = (parent.img.destHeight - textAreaTop) + 'px';
1906
- }
1907
- break;
1908
- case 90:
1909
- if (flip.toLowerCase() === 'horizontal') {
1910
- parent.textArea.style.maxHeight = (parent.img.destWidth - (parseFloat(parent.textArea.style.left) -
1911
- parent.img.destLeft)) + 'px';
1912
- } else {
1913
- parent.textArea.style.maxHeight = (parseFloat(parent.textArea.style.left) - parent.img.destLeft) + 'px';
1914
- }
1915
- break;
1916
- case 180:
1917
- if (flip.toLowerCase() === 'vertical') {
1918
- textAreaTop = parseFloat(parent.textArea.style.top) - parent.img.destTop;
1919
- parent.textArea.style.maxHeight = (parent.img.destHeight - textAreaTop) + 'px';
1920
- } else {
1921
- parent.textArea.style.maxHeight = (parseFloat(parent.textArea.style.top) - parent.img.destTop) + 'px';
1922
- }
1923
- break;
1924
- case 270:
1925
- if (flip.toLowerCase() === 'horizontal') {
1926
- parent.textArea.style.maxHeight = (parseFloat(parent.textArea.style.left) - parent.img.destLeft) + 'px';
1927
- } else {
1928
- parent.textArea.style.maxHeight = parent.img.destWidth - (parseFloat(parent.textArea.style.left)
1929
- - parent.img.destLeft) + 'px';
1930
- }
1931
- break;
1932
- }
1933
- }
1934
-
1935
- private updatePathRatio(obj: SelectionPoint): void {
1936
- const parent: ImageEditor = this.parent;
1937
- for (let i: number = 0, len: number = obj.pointColl.length; i < len; i++) {
1938
- const currPoint: Point = obj.pointColl[i as number];
1939
- currPoint.ratioX = (currPoint.x - parent.img.destLeft) / parent.img.destWidth;
1940
- currPoint.ratioY = (currPoint.y - parent.img.destTop) / parent.img.destHeight;
1941
- }
1942
- }
1943
-
1944
- private stopPathDrawing(e: MouseEvent & TouchEvent, isApply: boolean): void {
1945
- const parent: ImageEditor = this.parent;
1946
- if (parent.activeObj.shape === 'path') {
1947
- const obj: Object = {shape: null };
1948
- parent.notify('selection', { prop: 'getCurrentDrawingShape', value: {obj: obj }});
1949
- if (obj['shape'] === 'path') {
1950
- const prevCropObj: CurrentObject = extend({}, parent.cropObj, {}, true) as CurrentObject;
1951
- const object: Object = {currObj: {} as CurrentObject };
1952
- parent.notify('filter', { prop: 'getCurrentObj', onPropertyChange: false, value: {object: object }});
1953
- const prevObj: CurrentObject = object['currObj'];
1954
- prevObj.objColl = extend([], parent.objColl, [], true) as SelectionPoint[];
1955
- prevObj.pointColl = extend([], parent.pointColl, [], true) as Point[];
1956
- prevObj.afterCropActions = extend([], parent.afterCropActions, [], true) as string[];
1957
- const selPointCollObj: Object = {selPointColl: null };
1958
- parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
1959
- value: {obj: selPointCollObj }});
1960
- prevObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true) as Point[];
1961
- parent.notify('selection', { prop: 'setCurrentDrawingShape', value: {value: '' }});
1962
- parent.currObjType.isDragging = false;
1963
- if (e && e.type !== 'touchstart' && isNullOrUndefined(isApply)) {parent.activeObj.pointColl.pop(); }
1964
- this.updatePathRatio(parent.activeObj);
1965
- if (isNullOrUndefined(parent.activeObj.imageRatio)) {
1966
- parent.notify('shape', { prop: 'updImgRatioForActObj', onPropertyChange: false});
1967
- }
1968
- parent.objColl.push(parent.activeObj);
1969
- parent.notify('undo-redo', { prop: 'updateUndoRedoColl', onPropertyChange: false,
1970
- value: {operation: 'shapeTransform', previousObj: prevObj, previousObjColl: prevObj.objColl,
1971
- previousPointColl: prevObj.pointColl, previousSelPointColl: prevObj.selPointColl,
1972
- previousCropObj: prevCropObj, previousText: null,
1973
- currentText: null, previousFilter: null, isCircleCrop: null}});
1974
- parent.objColl.pop();
1975
- if (e) {
1976
- parent.notify('selection', { prop: 'mouseUpEventHandler', value: {e: e }});
1977
- this.lowerContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
1978
- parent.notify('draw', { prop: 'redrawImgWithObj', onPropertyChange: false});
1979
- if (parent.objColl.length > 0) {
1980
- const obj1: ActivePoint = parent.activeObj.activePoint;
1981
- const obj2: ActivePoint = parent.objColl[parent.objColl.length - 1].activePoint;
1982
- if (Math.floor(obj1.startX) === Math.floor(obj2.startX) &&
1983
- Math.floor(obj1.startY) === Math.floor(obj2.startY) &&
1984
- Math.floor(obj1.endX) === Math.floor(obj2.endX) &&
1985
- Math.floor(obj1.endY) === Math.floor(obj2.endY)) {
1986
- this.refreshActiveObj();
1987
- }
1988
- }
1989
- }
1990
- parent.notify('draw', { prop: 'setNewPath', value: {bool: true }});
1991
- if (parent.objColl[parent.objColl.length - 1]) {
1992
- const shape: string = parent.drawingShape;
1993
- parent.notify('selection', { prop: 'setCurrentDrawingShape', value: {value: '' }});
1994
- parent.noRedact = true;
1995
- parent.selectShape(parent.objColl[parent.objColl.length - 1].currIndex);
1996
- parent.notify('selection', { prop: 'setCurrentDrawingShape', value: {value: 'path' }});
1997
- parent.drawingShape = shape;
1998
- }
1999
- parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: {isPenEdit: null} });
2000
- const obj: Object = {shapeSettingsObj: {} as ShapeSettings };
2001
- parent.notify('selection', { prop: 'updatePrevShapeSettings', onPropertyChange: false, value: {obj: obj}});
2002
- const shapeSettings: ShapeSettings = obj['shapeSettingsObj'];
2003
- const shapeResizingArgs: ShapeChangeEventArgs = {cancel: false, action: 'draw-end', previousShapeSettings: shapeSettings};
2004
- const shapeMovingArgs: ShapeChangeEventArgs = {cancel: false, action: 'move', previousShapeSettings: shapeSettings};
2005
- parent.notify('selection', { prop: 'triggerShapeChange', onPropertyChange: false,
2006
- value: {shapeResizingArgs: shapeResizingArgs, shapeMovingArgs: shapeMovingArgs, type: 'mouse-up'}});
2007
- parent.notify('undo-redo', { prop: 'updateUndoRedoStack', onPropertyChange: false });
2008
- }
2009
- }
2010
- }
2011
-
2012
- private findTextTarget(e: MouseEvent & TouchEvent): void {
2013
- const parent: ImageEditor = this.parent;
2014
- if (!e) {return; }
2015
- if (parent.activeObj.shape !== 'text') {
2016
- if (parent.activeObj.shape === 'path') {
2017
- this.stopPathDrawing(e, null);
2018
- return;
2019
- } else if (e.type === 'dblclick') {
2020
- parent.notify('selection', { prop: 'setPanDown', onPropertyChange: false, value: {panDown: null }});
2021
- const activeObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
2022
- const objColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
2023
- const obj: Object = {bool: null };
2024
- parent.notify('selection', { prop: 'findTargetObj', onPropertyChange: false,
2025
- value: {x: e.clientX, y: e.clientY, isCrop: false, obj: obj }});
2026
- parent.objColl = objColl;
2027
- if (!obj['bool'] || parent.activeObj.shape !== 'text') {
2028
- parent.activeObj = extend({}, activeObj, {}, true) as SelectionPoint;
2029
- return;
2030
- }
2031
- } else {
2032
- return;
2033
- }
2034
- }
2035
- let x: number; let y: number;
2036
- if (e.type === 'dblclick') {x = e.clientX; y = e.clientY; }
2037
- else if (e.type === 'touchstart') {
2038
- x = e.touches[0].clientX; y = e.touches[0].clientY;
2039
- parent.notify('selection', { prop: 'setTouchEndPoint', onPropertyChange: false,
2040
- value: {x: e.touches[0].clientX, y: e.touches[0].clientY}});
2041
- }
2042
- parent.notify('toolbar', { prop: 'setPreventZoomBtn', onPropertyChange: false, value: {isPrevent: true }});
2043
- parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'text',
2044
- isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
2045
- parent.notify('toolbar', { prop: 'setPreventZoomBtn', onPropertyChange: false, value: {isPrevent: false }});
2046
- parent.notify('toolbar', { prop: 'update-toolbar-items', onPropertyChange: false});
2047
- if (!isNullOrUndefined(x) && !isNullOrUndefined(y)) {
2048
- const bbox: DOMRect = parent.lowerCanvas.getBoundingClientRect() as DOMRect;
2049
- x -= bbox.left; y -= bbox.top; let flip: string = '';
2050
- const degree: number = this.getRotDegOfShape(parent.activeObj);
2051
- if (parent.activeObj.textFlip === '') {
2052
- if (parent.activeObj.textFlip === parent.transform.currFlipState) {flip = ''; }
2053
- else {flip = parent.transform.currFlipState; }
2054
- } else {
2055
- if (parent.activeObj.textFlip === parent.transform.currFlipState) {flip = ''; }
2056
- else if (parent.transform.currFlipState === '') {flip = parent.activeObj.textFlip; }
2057
- else {flip = parent.transform.currFlipState; }
2058
- }
2059
- let temp: SelectionPoint;
2060
- if (parent.textArea.style.display === 'none') {
2061
- temp = extend({}, parent.activeObj, {}, true) as SelectionPoint;
2062
- for (let i: number = 0; i < parent.objColl.length; i++) {
2063
- if (JSON.stringify(parent.activeObj) === JSON.stringify(parent.objColl[i as number])) {
2064
- parent.objColl.splice(i, 1);
2065
- }
2066
- }
2067
- this.refreshActiveObj();
2068
- this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
2069
- this.lowerContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
2070
- parent.notify('draw', { prop: 'redrawImgWithObj', onPropertyChange: false});
2071
- parent.notify('draw', { prop: 'redrawDownScale' });
2072
- parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.lowerContext}});
2073
- parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.upperContext}});
2074
- if ((parent.currSelectionPoint && parent.currSelectionPoint.shape === 'crop-circle') || parent.isCircleCrop) {
2075
- parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
2076
- value: {context: this.lowerContext, isSave: null, isFlip: null}});
2077
- }
2078
- parent.activeObj = temp; this.updateFontStyles();
2079
- const actObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
2080
- const radius: number = actObj.topLeftCircle.radius;
2081
- const { startX, startY, endX, endY, width, height } = actObj.activePoint;
2082
- const center: Point = {x: startX + (width / 2), y: startY +
2083
- (height / 2)};
2084
- const cosAngle: number = Math.cos(actObj.rotatedAngle);
2085
- const sinAngle: number = Math.sin(actObj.rotatedAngle);
2086
- const p1: Point = { x: cosAngle * (startX - center.x) - sinAngle * (startY - center.y) + center.x,
2087
- y: sinAngle * (startX - center.x) + cosAngle * (startY - center.y) + center.y };
2088
- const p2: Point = { x: cosAngle * (endX - center.x) - sinAngle * (startY - center.y) + center.x,
2089
- y: sinAngle * (endX - center.x) + cosAngle * (startY - center.y) + center.y };
2090
- const p3: Point = { x: cosAngle * (startX - center.x) - sinAngle * (endY - center.y) + center.x,
2091
- y: sinAngle * (startX - center.x) + cosAngle * (endY - center.y) + center.y };
2092
- const p4: Point = { x: cosAngle * (endX - center.x) - sinAngle * (endY - center.y) + center.x,
2093
- y: sinAngle * (endX - center.x) + cosAngle * (endY - center.y) + center.y };
2094
- const obj: Object = {position: null, x: x, y: y, x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y,
2095
- x3: p3.x, y3: p3.y, x4: p4.x, y4: p4.y };
2096
- parent.notify('draw', { prop: 'checkPointPosition', onPropertyChange: false, value: {obj: obj }});
2097
- if ((actObj.rotatedAngle !== 0 && (obj['position'] === 'inside' || obj['position'] === 'on')) ||
2098
- (actObj.rotatedAngle === 0 && x >= (actObj.activePoint.startX - (radius * 2)) &&
2099
- x <= (actObj.activePoint.endX + (radius * 2)) &&
2100
- y >= (actObj.activePoint.startY - (radius * 2)) &&
2101
- y <= (actObj.activePoint.endY + (radius * 2)))) {
2102
- this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
2103
- if (actObj.flipObjColl.length === 4) {
2104
- actObj.flipObjColl = []; flip = ''; actObj.shapeFlip = '';
2105
- }
2106
- if (flip === '' && actObj.flipObjColl.length > 1) {
2107
- flip = actObj.flipObjColl[actObj.flipObjColl.length - 1];
2108
- }
2109
- if (actObj.flipObjColl.length <= 1) {
2110
- const points: Point = this.setTextBoxPos(actObj, degree, flip, x, y);
2111
- x = points.x; y = points.y;
2112
- } else {
2113
- const points: Point = this.setTextBoxPoints(actObj, degree, flip, x, y);
2114
- x = points.x; y = points.y;
2115
- }
2116
- if (parent.activeObj.rotatedAngle !== 0) {
2117
- let point: Point = this.getTextBoxPosition(parent.activeObj);
2118
- x = point.x; y = point.y;
2119
- point = this.setFlipState(x, y, parent.activeObj);
2120
- x = point.x; y = point.y;
2121
- }
2122
- this.renderTextArea(x, y, actObj);
2123
-
2124
- } else {this.applyActObj(); }
2125
- }
2126
- } else if ((parent.textArea.style.display === 'block' || parent.textArea.style.display === 'inline-block')
2127
- && this.selectedText() !== '' && e.type === 'mousedown') {
2128
- const temp: string = parent.textArea.value; parent.textArea.value += 'a'; parent.textArea.value = temp;
2129
- } else if (parent.textArea.style.display === 'none') {
2130
- parent.textArea.style.display = 'block';
2131
- }
2132
- }
2133
-
2134
- private getTextBoxPosition(obj: SelectionPoint, object?: Object): Point {
2135
- let point: Point = {x: 0, y: 0 };
2136
- const { startX, startY, endX, endY, width, height } = obj.activePoint;
2137
- const center: Point = {x: startX + (width / 2), y: startY + (height / 2)};
2138
- const cosAngle: number = Math.cos(obj.rotatedAngle);
2139
- const sinAngle: number = Math.sin(obj.rotatedAngle);
2140
- const p1: Point = { x: cosAngle * (startX - center.x) - sinAngle * (startY - center.y) + center.x,
2141
- y: sinAngle * (startX - center.x) + cosAngle * (startY - center.y) + center.y };
2142
- const p2: Point = { x: cosAngle * (endX - center.x) - sinAngle * (startY - center.y) + center.x,
2143
- y: sinAngle * (endX - center.x) + cosAngle * (startY - center.y) + center.y };
2144
- const p3: Point = { x: cosAngle * (startX - center.x) - sinAngle * (endY - center.y) + center.x,
2145
- y: sinAngle * (startX - center.x) + cosAngle * (endY - center.y) + center.y };
2146
- const p4: Point = { x: cosAngle * (endX - center.x) - sinAngle * (endY - center.y) + center.x,
2147
- y: sinAngle * (endX - center.x) + cosAngle * (endY - center.y) + center.y };
2148
- const degree: number = this.getRotDegOfShape(obj);
2149
- if (degree === 0 || degree === 360) {point = {x: p1.x, y: p1.y}; }
2150
- else if (degree === 90 || degree === -270) {point = {x: p2.x, y: p2.y}; }
2151
- else if (degree === 180 || degree === -180) {point = {x: p4.x, y: p4.y}; }
2152
- else if (degree === 270 || degree === -90) {point = {x: p3.x, y: p3.y}; }
2153
- if (object) {object['x'] = point.x; object['y'] = point.y; }
2154
- return point;
2155
- }
2156
-
2157
- private setFlipState(x: number, y: number, obj: SelectionPoint, object?: Object): Point {
2158
- const parent: ImageEditor = this.parent; const panObj: Object = {panRegion: '' };
2159
- const { clientWidth, clientHeight } = parent.lowerCanvas;
2160
- let center: Point = {x: 0, y: 0};
2161
- parent.notify('crop', { prop: 'getCurrFlipState', onPropertyChange: false,
2162
- value: {panObj: panObj }});
2163
- if (panObj['panRegion'] !== '') {
2164
- if (panObj['panRegion'] === 'horizontal') {
2165
- center.x = clientWidth - (clientWidth / 2);
2166
- x = (center.x - x) + center.x;
2167
- } else if (panObj['panRegion'] === 'vertical') {
2168
- center.y = clientHeight - (clientHeight / 2);
2169
- y = (center.y - y) + center.y;
2170
- } else {
2171
- center = {x: clientWidth - (clientWidth / 2), y: clientHeight - (clientHeight / 2)};
2172
- x = (center.x - x) + center.x;
2173
- y = (center.y - y) + center.y;
2174
- }
2175
- }
2176
- if (object) {object['x'] = x; object['y'] = y; }
2177
- return {x: x, y: y};
2178
- }
2179
-
2180
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2181
- private fileChanged(e: any): void {
2182
- /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
2183
- const filesData: FileList = (e.target as any).files[0];
2184
- /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
2185
- const fileData: any = filesData;
2186
- const fileExtension: string = fileData.name && fileData.name.split('.').pop().toLowerCase();
2187
- if (fileExtension && ['jpg', 'jpeg', 'png', 'svg', 'webp', 'bmp'].indexOf(fileExtension) === -1) {
2188
- this.refreshActiveObj();
2189
- return;
2190
- }
2191
- // eslint-disable-next-line @typescript-eslint/tslint/config, @typescript-eslint/no-explicit-any
2192
- const URL = window.URL; const url = URL.createObjectURL((e.target as any).files[0]);
2193
- this.onLoadImgShape(null, null, null, null, url.toString(), true);
2194
- (document.getElementById(this.parent.element.id + '_fileUpload') as HTMLInputElement).value = '';
2195
- }
2196
-
2197
- private onLoadImgShape(x: number, y: number, width: number, height: number, url: string | ImageData,
2198
- isSelect?: boolean, degree?: number, isAspectRatio?: boolean, opacity?: number, isSelected?: boolean): void {
2199
- // eslint-disable-next-line @typescript-eslint/no-this-alias
2200
- const proxy: Shape = this; const parent: ImageEditor = this.parent;
2201
- if (typeof(url) === 'string') {this.shapeImg.src = url; }
2202
- else {
2203
- parent.inMemoryCanvas.width = (url as ImageData).width;
2204
- parent.inMemoryCanvas.height = (url as ImageData).height;
2205
- parent.inMemoryCanvas.getContext('2d').putImageData((url as ImageData), 0, 0);
2206
- this.shapeImg.src = parent.inMemoryCanvas.toDataURL();
2207
- }
2208
- this.prevObjColl();
2209
- parent.activeObj.shape = 'image';
2210
- this.initShapeProps();
2211
- this.shapeImg.onload = () => {
2212
- proxy.upperContext.drawImage(proxy.shapeImg, 0, 0, proxy.shapeImg.width, proxy.shapeImg.height);
2213
- proxy.updateImgCanvas(isSelect, x, y, width, height, degree, isAspectRatio, opacity, isSelected);
2214
- };
2215
- }
2216
-
2217
- private updateImgCanvas(isSelect: boolean, x: number, y: number, width: number, height: number, degree: number,
2218
- isAspectRatio: boolean, opacity: number, isSelected?: boolean): void {
2219
- const parent: ImageEditor = this.parent;
2220
- parent.activeObj.imageElement = this.shapeImg;
2221
- parent.activeObj.imageCanvas = parent.createElement('canvas');
2222
- let dimObj: Object = {width: 0, height: 0 };
2223
- parent.notify('transform', { prop: 'calcMaxDimension', onPropertyChange: false,
2224
- value: {width: this.shapeImg.width, height: this.shapeImg.height, obj: dimObj, isImgShape: null }});
2225
- if (width && height) {
2226
- if (isAspectRatio) {
2227
- const obj: Object = {ratio: null };
2228
- parent.notify('selection', { prop: 'findImageRatio', onPropertyChange: false,
2229
- value: {width: this.shapeImg.width, height: this.shapeImg.height, obj: obj }});
2230
- dimObj = this.resizeImage(width, obj['ratio']);
2231
- } else {
2232
- dimObj = {width: width, height: height };
2233
- }
2234
- }
2235
- this.updateObj(dimObj, x, y);
2236
- parent.notify('draw', { prop: 'downScaleImgCanvas', onPropertyChange: false,
2237
- value: {ctx: parent.activeObj.imageCanvas.getContext('2d'), isImgAnnotation: true, isHFlip: null, isVFlip: null }});
2238
- parent.notify('transform', { prop: 'calcMaxDimension', onPropertyChange: false,
2239
- value: {width: this.shapeImg.width, height: this.shapeImg.height, obj: dimObj, isImgShape: true }});
2240
- if (width && height) {
2241
- if (isAspectRatio) {
2242
- const obj: Object = {ratio: null };
2243
- parent.notify('selection', { prop: 'findImageRatio', onPropertyChange: false,
2244
- value: {width: this.shapeImg.width, height: this.shapeImg.height, obj: obj }});
2245
- dimObj = this.resizeImage(width, obj['ratio']);
2246
- } else {
2247
- dimObj = {width: width, height: height };
2248
- }
2249
- }
2250
- if (opacity !== null && opacity !== undefined) {parent.activeObj.opacity = opacity; }
2251
- this.updateObj(dimObj, x, y);
2252
- parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate' }});
2253
- this.shapeImg = null;
2254
- if (degree) {
2255
- parent.activeObj.rotatedAngle = degree * (Math.PI / 180);
2256
- parent.notify('selection', {prop: 'updPtCollForShpRot', onPropertyChange: false, value: {obj: parent.activeObj }});
2257
- }
2258
- const obj: Object = {shapeSettingsObj: {} as ShapeSettings };
2259
- parent.notify('selection', { prop: 'updatePrevShapeSettings', onPropertyChange: false, value: {obj: obj}});
2260
- const shapeSettings: ShapeSettings = obj['shapeSettingsObj'];
2261
- const shapeChangingArgs: ShapeChangeEventArgs = {cancel: false, action: 'insert', previousShapeSettings: shapeSettings,
2262
- currentShapeSettings: shapeSettings};
2263
- parent.trigger('shapeChanging', shapeChangingArgs);
2264
- parent.editCompleteArgs = shapeChangingArgs;
2265
- isSelect = isSelect ? isSelect : isSelected;
2266
- this.drawShapeImageEvent(shapeChangingArgs, isSelect);
2267
- if (parent.isPublicMethod && !isSelected) {
2268
- parent.notify('undo-redo', {prop: 'updateUndoRedo', onPropertyChange: false});
2269
- } else if (!parent.isPublicMethod) {
2270
- parent.notify('undo-redo', { prop: 'updateUndoRedoStack', onPropertyChange: false});
2271
- }
2272
- parent.isPublicMethod = false;
2273
- }
2274
-
2275
- private updateObj(dimObj: Object, x: number, y: number): void {
2276
- const parent: ImageEditor = this.parent;
2277
- parent.activeObj.activePoint.width = dimObj['width'];
2278
- parent.activeObj.activePoint.height = dimObj['height'];
2279
- parent.activeObj.activePoint.startX = x ? x : (parent.lowerCanvas.width / 2) - (dimObj['width'] / 2);
2280
- parent.activeObj.activePoint.startY = y ? y : (parent.lowerCanvas.height / 2) - (dimObj['height'] / 2);
2281
- parent.activeObj.activePoint.endX = parent.activeObj.activePoint.startX + dimObj['width'];
2282
- parent.activeObj.activePoint.endY = parent.activeObj.activePoint.startY + dimObj['height'];
2283
- }
2284
-
2285
- private resizeImage(newWidth: number, aspectRatio: string): Object {
2286
- const aspectRatioArray: string[] = aspectRatio.split(':');
2287
- const aspectRatioWidth: number = parseInt(aspectRatioArray[0], 10);
2288
- const aspectRatioHeight: number = parseInt(aspectRatioArray[1], 10);
2289
- const newHeight: number = Math.round((newWidth * aspectRatioHeight) / aspectRatioWidth);
2290
- return { width: newWidth, height: newHeight };
2291
- }
2292
-
2293
- private setTextBoxPos(actObj: SelectionPoint, degree: number, flip: string, x: number, y: number): Point {
2294
- const point: Point = {x: x, y: y};
2295
- const { startX, startY, endX, endY } = actObj.activePoint;
2296
- flip = flip.toLowerCase();
2297
- switch (degree) {
2298
- case 0:
2299
- if (flip === 'horizontal') {
2300
- point.x = endX; point.y = startY;
2301
- } else if (flip === 'vertical') {
2302
- point.x = startX; point.y = endY;
2303
- } else {
2304
- point.x = startX; point.y = startY;
2305
- }
2306
- break;
2307
- case 90:
2308
- if (flip === 'horizontal') {
2309
- point.x = startX; point.y = startY;
2310
- } else if (flip === 'vertical') {
2311
- point.x = endX; point.y = endY;
2312
- } else {
2313
- point.x = endX; point.y = startY;
2314
- }
2315
- break;
2316
- case 180:
2317
- if (flip === 'horizontal') {
2318
- point.x = startX; point.y = endY;
2319
- } else if (flip === 'vertical') {
2320
- point.x = endX; point.y = startY;
2321
- } else {
2322
- point.x = endX; point.y = endY;
2323
- }
2324
- break;
2325
- case 270:
2326
- if (flip === 'horizontal') {
2327
- point.x = endX; point.y = endY;
2328
- } else if (flip === 'vertical') {
2329
- point.x = startX; point.y = startY;
2330
- } else {
2331
- point.x = startX; point.y = endY;
2332
- }
2333
- break;
2334
- }
2335
- return point;
2336
- }
2337
-
2338
- private setTextBoxPoints(actObj: SelectionPoint, degree: number, flip: string, x: number, y: number): Point {
2339
- const point: Point = {x: x, y: y};
2340
- const { startX, startY, endX, endY } = actObj.activePoint;
2341
- flip = flip.toLowerCase();
2342
- switch (degree) {
2343
- case 0:
2344
- if (actObj.flipObjColl[0] && actObj.flipObjColl[0].toLowerCase() === 'horizontal') {
2345
- if (flip === 'horizontal') {
2346
- point.x = startX; point.y = startY;
2347
- } else if (flip === 'vertical') {
2348
- point.x = endX; point.y = endY;
2349
- }
2350
- } else {
2351
- if (flip === 'horizontal') {
2352
- point.x = endX; point.y = endY;
2353
- } else if (flip === 'vertical') {
2354
- point.x = endX; point.y = startY;
2355
- }
2356
- }
2357
- break;
2358
- case 90:
2359
- if (actObj.flipObjColl[0] && actObj.flipObjColl[0].toLowerCase() === 'horizontal') {
2360
- if (flip === 'horizontal') {
2361
- point.x = endX; point.y = endY;
2362
- } else if (flip === 'vertical') {
2363
- point.x = startX; point.y = endY;
2364
- }
2365
- } else {
2366
- if (flip === 'horizontal') {
2367
- point.x = startX; point.y = endY;
2368
- } else if (flip === 'vertical') {
2369
- point.x = startX; point.y = startY;
2370
- }
2371
- }
2372
- break;
2373
- case 180:
2374
- if (actObj.flipObjColl[0] && actObj.flipObjColl[0].toLowerCase() === 'horizontal') {
2375
- if (flip === 'horizontal') {
2376
- point.x = startX; point.y = startY;
2377
- } else if (flip === 'vertical') {
2378
- point.x = startX; point.y = startY;
2379
- }
2380
- } else {
2381
- if (flip === 'horizontal') {
2382
- point.x = startX; point.y = startY;
2383
- } else if (flip === 'vertical') {
2384
- point.x = startX; point.y = endY;
2385
- }
2386
- }
2387
- break;
2388
- case 270:
2389
- if (actObj.flipObjColl[0] && actObj.flipObjColl[0].toLowerCase() === 'horizontal') {
2390
- if (flip === 'horizontal') {
2391
- point.x = startX; point.y = startY;
2392
- } else if (flip === 'vertical') {
2393
- point.x = endX; point.y = startY;
2394
- }
2395
- } else {
2396
- if (flip === 'horizontal') {
2397
- point.x = endX; point.y = startY;
2398
- } else if (flip === 'vertical') {
2399
- point.x = endX; point.y = endY;
2400
- }
2401
- }
2402
- break;
2403
- }
2404
- return point;
2405
- }
2406
-
2407
- private selectedText(): string {
2408
- const parent: ImageEditor = this.parent;
2409
- const start: number = parent.textArea.selectionStart;
2410
- const finish: number = parent.textArea.selectionEnd;
2411
- return parent.textArea.value.substring(start, finish);
2412
- }
2413
-
2414
- private panObjColl(xDiff: number, yDiff: number, panRegion: string): void {
2415
- const parent: ImageEditor = this.parent;
2416
- if (parent.objColl.length > 0) {
2417
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
2418
- let currObj: SelectionPoint = parent.objColl[i as number];
2419
- if (panRegion === '') {
2420
- currObj.activePoint.startX += xDiff;
2421
- currObj.activePoint.endX += xDiff;
2422
- if (currObj.rotationCirclePointColl) {
2423
- currObj.rotationCirclePointColl.x += xDiff;
2424
- }
2425
- if (currObj.shape === 'path') {
2426
- for (let l: number = 0, len: number = currObj.pointColl.length; l < len; l++) {
2427
- currObj.pointColl[l as number].x += xDiff;
2428
- }
2429
- }
2430
- currObj.activePoint.startY += yDiff;
2431
- currObj.activePoint.endY += yDiff;
2432
- if (currObj.rotationCirclePointColl) {
2433
- currObj.rotationCirclePointColl.y += yDiff;
2434
- }
2435
- if (currObj.shape === 'path') {
2436
- for (let l: number = 0; l < currObj.pointColl.length; l++) {
2437
- currObj.pointColl[l as number].y += yDiff;
2438
- }
2439
- }
2440
- }
2441
- currObj = this.updateWidthHeight(currObj);
2442
- parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value:
2443
- {actPoint: currObj.activePoint,
2444
- obj: currObj}});
2445
- if (currObj.shape === 'line' || currObj.shape === 'arrow') {
2446
- currObj.pointColl = this.getLinePoints(currObj.activePoint.startX, currObj.activePoint.startY, currObj.activePoint.endX,
2447
- currObj.activePoint.endY);
2448
- for (let j: number = 0, len: number = currObj.pointColl.length; j < len; j++) {
2449
- currObj.pointColl[j as number].ratioX =
2450
- (currObj.pointColl[j as number].x - parent.img.destLeft) / parent.img.destWidth;
2451
- currObj.pointColl[j as number].ratioY =
2452
- (currObj.pointColl[j as number].y - parent.img.destTop) / parent.img.destHeight;
2453
- }
2454
- }
2455
- this.refreshActiveObj();
2456
- }
2457
- const temp: string = this.lowerContext.filter; this.lowerContext.filter = 'none';
2458
- this.iterateObjColl();
2459
- this.lowerContext.filter = temp; this.refreshActiveObj();
2460
- parent.notify('draw', {prop: 'applyFrame', value: {ctx: this.lowerContext, frame: parent.frameObj.type, preventImg: true}});
2461
- }
2462
- }
2463
-
2464
- private updateFontStyles(isTextBox?: boolean): void {
2465
- const parent: ImageEditor = this.parent;
2466
- this.upperContext.strokeStyle = parent.activeObj.strokeSettings.strokeColor;
2467
- this.upperContext.fillStyle = parent.activeObj.strokeSettings.strokeColor;
2468
- let textStyle: string = '';
2469
- if (parent.activeObj.textSettings.bold) {textStyle = 'bold '; }
2470
- if (parent.activeObj.textSettings.italic) {textStyle = 'italic '; }
2471
- if (parent.activeObj.textSettings.bold && parent.activeObj.textSettings.italic) {textStyle = 'italic bold '; }
2472
- const fontSize: number = isTextBox ? parseFloat(parent.textArea.style.fontSize) : parent.activeObj.textSettings.fontSize;
2473
- const fontFamily: string = (parent.textArea.style.display === 'block' || parent.textArea.style.display === 'inline-block') ?
2474
- parent.textArea.style.fontFamily : parent.activeObj.textSettings.fontFamily;
2475
- this.upperContext.font = textStyle + fontSize + 'px' + ' ' + fontFamily;
2476
- }
2477
-
2478
- private applyFontStyle(item: string): void {
2479
- const parent: ImageEditor = this.parent;
2480
- const obj: Object = {shapeSettingsObj: {} as ShapeSettings };
2481
- parent.notify('selection', { prop: 'updatePrevShapeSettings', onPropertyChange: false, value: {obj: obj}});
2482
- const shapeSettings: ShapeSettings = obj['shapeSettingsObj'];
2483
- let isObjPushed: boolean = false;
2484
- const collLength: number = parent.objColl.length;
2485
- this.pushActItemIntoObj();
2486
- if (collLength !== parent.objColl.length) {isObjPushed = true; }
2487
- const objColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
2488
- if (isObjPushed) {
2489
- parent.objColl.pop();
2490
- }
2491
- if (parent.textArea.style.display === 'none') { this.updateFontRatio(parent.activeObj); }
2492
- else { this.updateFontRatio(parent.activeObj, true); }
2493
- switch (item) {
2494
- case 'default':
2495
- this.updateFontStyle(item, objColl, 'normal', 'normal', false, false);
2496
- break;
2497
- case 'bold':
2498
- this.updateFontStyle(item, objColl, 'bold', 'normal', false, false);
2499
- break;
2500
- case 'italic':
2501
- this.updateFontStyle(item, objColl, 'normal', 'italic', false, false);
2502
- break;
2503
- case 'bolditalic':
2504
- this.updateFontStyle(item, objColl, 'bold', 'italic', false, false);
2505
- break;
2506
- case 'underline':
2507
- this.updateFontStyle(item, objColl, 'normal', 'normal', true, false);
2508
- break;
2509
- case 'boldunderline':
2510
- this.updateFontStyle(item, objColl, 'bold', 'normal', true, false);
2511
- break;
2512
- case 'italicunderline':
2513
- this.updateFontStyle(item, objColl, 'normal', 'italic', true, false);
2514
- break;
2515
- case 'bolditalicunderline':
2516
- this.updateFontStyle(item, objColl, 'bold', 'italic', true, false);
2517
- break;
2518
- case 'strikethrough':
2519
- this.updateFontStyle(item, objColl, 'normal', 'normal', false, true);
2520
- break;
2521
- case 'boldstrikethrough':
2522
- this.updateFontStyle(item, objColl, 'bold', 'normal', false, true);
2523
- break;
2524
- case 'italicstrikethrough':
2525
- this.updateFontStyle(item, objColl, 'normal', 'italic', false, true);
2526
- break;
2527
- case 'underlinestrikethrough':
2528
- this.updateFontStyle(item, objColl, 'normal', 'normal', true, true);
2529
- break;
2530
- case 'bolditalicstrikethrough':
2531
- this.updateFontStyle(item, objColl, 'bold', 'italic', false, true);
2532
- break;
2533
- case 'boldunderlinestrikethrough':
2534
- this.updateFontStyle(item, objColl, 'bold', 'normal', true, true);
2535
- break;
2536
- case 'italicunderlinestrikethrough':
2537
- this.updateFontStyle(item, objColl, 'normal', 'italic', true, true);
2538
- break;
2539
- case 'bolditalicunderlinestrikethrough':
2540
- this.updateFontStyle(item, objColl, 'bold', 'italic', true, true);
2541
- break;
2542
- }
2543
- const shapeChangedArgs: ShapeChangeEventArgs = {action: 'font-style', currentShapeSettings: extend({}, shapeSettings, {}, true) as ShapeSettings};
2544
- shapeChangedArgs.currentShapeSettings.fontStyle = this.getFontStyleArray(item);
2545
- parent.trigger('shapeChange', shapeChangedArgs);
2546
- parent.editCompleteArgs = shapeChangedArgs;
2547
- }
2548
-
2549
- private getFontStyleArray(item: string): string[] {
2550
- const styleArray: string[] = [];
2551
- const lowerItem: string = item.toLowerCase();
2552
- if (lowerItem.indexOf('bold') > -1) {
2553
- styleArray.push('bold');
2554
- }
2555
- if (lowerItem.indexOf('italic') > -1) {
2556
- styleArray.push('italic');
2557
- }
2558
- if (lowerItem.indexOf('underline') > -1) {
2559
- styleArray.push('underline');
2560
- }
2561
- if (lowerItem.indexOf('strikethrough') > -1) {
2562
- styleArray.push('strikethrough');
2563
- }
2564
- return styleArray;
2565
- }
2566
-
2567
- private updateFontStyle(item: string, objColl: SelectionPoint[], fontWeight: string, fontStyle: string, underline: boolean,
2568
- strikethrough: boolean): void {
2569
- const parent: ImageEditor = this.parent;
2570
- const style: CSSStyleDeclaration = parent.textArea.style;
2571
- if (style.display === 'block' || style.display === 'inline-block') {
2572
- if (fontWeight === 'bold') {style.fontWeight = 'bold'; }
2573
- else {style.fontWeight = 'normal'; }
2574
- if (fontStyle === 'italic') {style.fontStyle = 'italic'; }
2575
- else {style.fontStyle = 'normal'; }
2576
- if (underline && strikethrough) {
2577
- style.textDecoration = 'underline line-through';
2578
- }
2579
- else if (strikethrough)
2580
- {
2581
- style.textDecoration = 'line-through';
2582
- }
2583
- else if (underline) {
2584
- style.textDecoration = 'underline';
2585
- }
2586
- else {
2587
- style.textDecoration = 'none';
2588
- }
2589
- const key: string = [
2590
- style.fontWeight === 'bold' ? 'bold' : '',
2591
- style.fontStyle === 'italic' ? 'italic' : '',
2592
- typeof style.textDecoration === 'string' && style.textDecoration.indexOf('underline') > -1 ? 'underline' : '',
2593
- typeof style.textDecoration === 'string' && style.textDecoration.indexOf('line-through') > -1 ? 'strikethrough' : ''
2594
- ].filter(Boolean).join('');
2595
- const valueMap: Record<string, string> = {
2596
- '': 'default',
2597
- bold: 'bold',
2598
- italic: 'italic',
2599
- underline: 'underline',
2600
- strikethrough: 'strikethrough',
2601
- bolditalic: 'bolditalic',
2602
- boldunderline: 'boldunderline',
2603
- boldstrikethrough: 'boldstrikethrough',
2604
- italicunderline: 'italicunderline',
2605
- italicstrikethrough: 'italicstrikethrough',
2606
- underlinestrikethrough: 'underlinestrikethrough',
2607
- bolditalicunderline: 'bolditalicunderline',
2608
- bolditalicstrikethrough: 'bolditalicstrikethrough',
2609
- boldunderlinestrikethrough: 'boldunderlinestrikethrough',
2610
- italicunderlinestrikethrough: 'italicunderlinestrikethrough',
2611
- bolditalicunderlinestrikethrough: 'bolditalicunderlinestrikethrough'
2612
- };
2613
- const value: string = key in valueMap ? valueMap[key as string] : 'default';
2614
- const width: number = this.getTextAreaWidth(value); style.width = width + 'px';
2615
- this.updateObjColl(item, objColl);
2616
- } else {
2617
- this.textSettings.bold = parent.activeObj.textSettings.bold = fontWeight === 'normal' ? false : true;
2618
- this.textSettings.italic = parent.activeObj.textSettings.italic = fontStyle === 'normal' ? false : true;
2619
- this.textSettings.underline = parent.activeObj.textSettings.underline = underline ? true : false;
2620
- this.textSettings.strikethrough = parent.activeObj.textSettings.strikethrough = strikethrough ? true : false;
2621
- if (parent.activeObj.activePoint.width !== 0 || parent.activeObj.activePoint.height !== 0) {
2622
- this.redrawText();
2623
- }
2624
- parent.notify('undo-redo', { prop: 'updateUrObj', onPropertyChange: false, value: {objColl: objColl}});
2625
- }
2626
- }
2627
-
2628
- private updateArrowRatio(obj: SelectionPoint): void {
2629
- const parent: ImageEditor = this.parent;
2630
- const object: Object = {arrowDimension: null };
2631
- parent.notify('draw', { prop: 'getArrowDimension', onPropertyChange: false, value: {obj: object }});
2632
- let length: number;
2633
- if (Math.abs(obj.activePoint.width) > Math.abs(obj.activePoint.height)) {length = Math.abs(obj.activePoint.width); }
2634
- else {length = Math.abs(obj.activePoint.height); }
2635
- let dimension: string; const dimensions: string[] = ['bar', 'arrow', 'arrowSolid', 'circle', 'square'];
2636
- for (dimension of dimensions) {
2637
- const ratioX: number = length / object['arrowDimension'][dimension as string]['width'];
2638
- const ratioY: number = length / object['arrowDimension'][dimension as string]['height'];
2639
- object['arrowDimension'][dimension as string]['ratioX'] = ratioX;
2640
- object['arrowDimension'][dimension as string]['ratioY'] = ratioY;
2641
- }
2642
- }
2643
-
2644
- private updateArrowSize(obj: SelectionPoint): void {
2645
- const object: Object = {arrowDimension: null };
2646
- this.parent.notify('draw', { prop: 'getArrowDimension', onPropertyChange: false, value: {obj: object }});
2647
- let length: number;
2648
- if (Math.abs(obj.activePoint.width) > Math.abs(obj.activePoint.height)) {length = Math.abs(obj.activePoint.width); }
2649
- else {length = Math.abs(obj.activePoint.height); }
2650
- let dimension: string; const dimensions: string[] = ['bar', 'arrow', 'arrowSolid', 'circle', 'square'];
2651
- for (dimension of dimensions) {
2652
- const ratioX: number = object['arrowDimension'][dimension as string]['ratioX'];
2653
- const ratioY: number = object['arrowDimension'][dimension as string]['ratioY'];
2654
- object['arrowDimension'][dimension as string]['width'] = length / ratioX;
2655
- object['arrowDimension'][dimension as string]['height'] = length / ratioY;
2656
- }
2657
- }
2658
-
2659
- private updateFontRatio(obj: SelectionPoint, isTextArea?: boolean): void {
2660
- const parent: ImageEditor = this.parent;
2661
- const text: string = this.getMaxText(isTextArea);
2662
- const width: number = this.upperContext.measureText(text).width +
2663
- parent.activeObj.textSettings.fontSize * 0.5;
2664
- const height: number = parent.activeObj.textSettings.fontSize;
2665
- const degree: number = this.getRotDegOfShape(obj);
2666
- if (isNullOrUndefined(isTextArea)) {
2667
- if (degree === 0 || Math.abs(degree) === 180) {
2668
- obj.textSettings.fontRatio = width / obj.textSettings.fontSize;
2669
- } else {
2670
- obj.textSettings.fontRatio = height / obj.textSettings.fontSize;
2671
- }
2672
- } else if (isTextArea) {
2673
- const transformObj: Object = {bool: false };
2674
- parent.notify('selection', { prop: 'getTransformedShape', onPropertyChange: false, value: {obj: transformObj}});
2675
- if (!transformObj['bool'] || degree === 0 || Math.abs(degree) === 180) {
2676
- obj.textSettings.fontRatio = width / parseFloat(parent.textArea.style.fontSize);
2677
- } else {
2678
- obj.textSettings.fontRatio = height / parseFloat(parent.textArea.style.fontSize);
2679
- }
2680
- }
2681
- }
2682
-
2683
- private updateFontSize(obj: SelectionPoint): void {
2684
- const degree: number = this.getRotDegOfShape(obj, true);
2685
- if (degree === 0 || Math.abs(degree) === 180) {
2686
- obj.textSettings.fontSize = (obj.activePoint.width / obj.textSettings.fontRatio);
2687
- } else {
2688
- obj.textSettings.fontSize = (obj.activePoint.height / obj.textSettings.fontRatio);
2689
- }
2690
- }
2691
-
2692
- private updateObjColl(item: string, objColl: SelectionPoint[]): void {
2693
- const parent: ImageEditor = this.parent;
2694
- const prevCropObj: CurrentObject = extend({}, parent.cropObj, {}, true) as CurrentObject;
2695
- const object: Object = {currObj: {} as CurrentObject };
2696
- parent.notify('filter', { prop: 'getCurrentObj', onPropertyChange: false, value: {object: object }});
2697
- const prevObj: CurrentObject = object['currObj'];
2698
- prevObj.objColl = objColl;
2699
- prevObj.pointColl = extend([], parent.pointColl, [], true) as Point[];
2700
- prevObj.afterCropActions = extend([], parent.afterCropActions, [], true) as string[];
2701
- const selPointCollObj: Object = {selPointColl: null };
2702
- parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
2703
- value: {obj: selPointCollObj }});
2704
- prevObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true) as Point[];
2705
- const textSettings: TextSettings = parent.activeObj.textSettings;
2706
- const tempBold: boolean = textSettings.bold;
2707
- const tempItalic: boolean = textSettings.italic;
2708
- const tempUnderline: boolean = textSettings.underline;
2709
- const tempStrikethrough: boolean = textSettings.strikethrough;
2710
- switch (item) {
2711
- case 'default':
2712
- textSettings.bold = false;
2713
- textSettings.italic = false;
2714
- textSettings.underline = false;
2715
- textSettings.strikethrough = false;
2716
- break;
2717
- case 'bold':
2718
- textSettings.bold = true;
2719
- textSettings.italic = false;
2720
- textSettings.underline = false;
2721
- textSettings.strikethrough = false;
2722
- break;
2723
- case 'italic':
2724
- textSettings.bold = false;
2725
- textSettings.italic = true;
2726
- textSettings.underline = false;
2727
- textSettings.strikethrough = false;
2728
- break;
2729
- case 'bolditalic':
2730
- textSettings.bold = true;
2731
- textSettings.italic = true;
2732
- textSettings.underline = false;
2733
- textSettings.strikethrough = false;
2734
- break;
2735
- case 'underline':
2736
- textSettings.bold = false;
2737
- textSettings.italic = false;
2738
- textSettings.underline = true;
2739
- textSettings.strikethrough = false;
2740
- break;
2741
- case 'boldunderline':
2742
- textSettings.bold = true;
2743
- textSettings.italic = false;
2744
- textSettings.underline = true;
2745
- textSettings.strikethrough = false;
2746
- break;
2747
- case 'italicunderline':
2748
- textSettings.bold = false;
2749
- textSettings.italic = true;
2750
- textSettings.underline = true;
2751
- textSettings.strikethrough = false;
2752
- break;
2753
- case 'bolditalicunderline':
2754
- textSettings.bold = true;
2755
- textSettings.italic = true;
2756
- textSettings.underline = true;
2757
- textSettings.strikethrough = false;
2758
- break;
2759
- case 'strikethrough':
2760
- textSettings.bold = false;
2761
- textSettings.italic = false;
2762
- textSettings.underline = false;
2763
- textSettings.strikethrough = true;
2764
- break;
2765
- case 'boldstrikethrough':
2766
- textSettings.bold = true;
2767
- textSettings.italic = false;
2768
- textSettings.underline = false;
2769
- textSettings.strikethrough = true;
2770
- break;
2771
- case 'italicstrikethrough':
2772
- textSettings.bold = false;
2773
- textSettings.italic = true;
2774
- textSettings.underline = false;
2775
- textSettings.strikethrough = true;
2776
- break;
2777
- case 'underlinestrikethrough':
2778
- textSettings.bold = false;
2779
- textSettings.italic = false;
2780
- textSettings.underline = true;
2781
- textSettings.strikethrough = true;
2782
- break;
2783
- case 'bolditalicstrikethrough':
2784
- textSettings.bold = true;
2785
- textSettings.italic = true;
2786
- textSettings.underline = false;
2787
- textSettings.strikethrough = true;
2788
- break;
2789
- case 'boldunderlinestrikethrough':
2790
- textSettings.bold = true;
2791
- textSettings.italic = false;
2792
- textSettings.underline = true;
2793
- textSettings.strikethrough = true;
2794
- break;
2795
- case 'italicunderlinestrikethrough':
2796
- textSettings.bold = false;
2797
- textSettings.italic = true;
2798
- textSettings.underline = true;
2799
- textSettings.strikethrough = true;
2800
- break;
2801
- case 'bolditalicunderlinestrikethrough':
2802
- textSettings.bold = true;
2803
- textSettings.italic = true;
2804
- textSettings.underline = true;
2805
- textSettings.strikethrough = true;
2806
- break;
2807
- }
2808
- parent.objColl.push(parent.activeObj);
2809
- parent.notify('undo-redo', { prop: 'updateUndoRedoColl', onPropertyChange: false,
2810
- value: {operation: 'textAreaCustomization', previousObj: prevObj, previousObjColl: prevObj.objColl,
2811
- previousPointColl: prevObj.pointColl, previousSelPointColl: prevObj.selPointColl,
2812
- previousCropObj: prevCropObj, previousText: null,
2813
- currentText: null, previousFilter: null, isCircleCrop: null}});
2814
- parent.objColl.pop();
2815
- textSettings.bold = tempBold; textSettings.italic = tempItalic;
2816
- textSettings.underline = tempUnderline; textSettings.strikethrough = tempStrikethrough;
2817
- }
2818
-
2819
- private pushActItemIntoObj(): void {
2820
- const parent: ImageEditor = this.parent;
2821
- if (parent.textArea.style.display === 'none') {
2822
- if (parent.activeObj.activePoint.width !== 0 || parent.activeObj.activePoint.height !== 0) {
2823
- parent.objColl.push(parent.activeObj);
2824
- }
2825
- } else {
2826
- const temp: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
2827
- parent.notify('selection', { prop: 'setTextBoxStylesToActObj', onPropertyChange: false });
2828
- parent.objColl.push(parent.activeObj); parent.activeObj = temp;
2829
- }
2830
- }
2831
-
2832
- private clearActObj(): void {
2833
- const parent: ImageEditor = this.parent;
2834
- if (parent.textArea.style.display === 'none') {
2835
- this.refreshActiveObj(); this.applyActObj();
2836
- this.refreshActiveObj(); parent.currObjType.isCustomCrop = false;
2837
- }
2838
- }
2839
-
2840
- private refreshActiveObj(): void {
2841
- const parent: ImageEditor = this.parent;
2842
- parent.activeObj = {} as SelectionPoint;
2843
- parent.activeObj.activePoint = {startX: 0, startY: 0, endX: 0, endY: 0, width: 0, height: 0};
2844
- parent.activeObj.triangle = []; parent.activeObj.triangleRatio = []; parent.activeObj.order = null;
2845
- parent.activeObj.flipObjColl = []; parent.activeObj.strokeSettings = this.strokeSettings;
2846
- parent.activeObj.textSettings = this.textSettings; parent.activeObj.rotatedAngle = 0;
2847
- parent.activeObj.opacity = 1;
2848
- parent.activeObj.redactType = this.redactType;
2849
- parent.activeObj.redactBlur = parent.tempRedactBlur;
2850
- parent.activeObj.redactPixelate = parent.tempRedactPixel;
2851
- }
2852
-
2853
- private applyActObj(isMouseDown?: boolean): void {
2854
- const parent: ImageEditor = this.parent;
2855
- let isActObj: boolean = false;
2856
- if (parent.activeObj.shape !== undefined && parent.activeObj.shape === 'text' && parent.activeObj.keyHistory === '') {
2857
- this.refreshActiveObj();
2858
- this.upperContext.clearRect(0, 0 , parent.upperCanvas.width, parent.upperCanvas.height);
2859
- } else {
2860
- let splitWords: string[]; let isCropSelection: boolean = false;
2861
- if (parent.activeObj.shape !== undefined) {splitWords = parent.activeObj.shape.split('-'); }
2862
- if (splitWords === undefined && parent.currObjType.isCustomCrop) {isCropSelection = true; }
2863
- else if (splitWords !== undefined && splitWords[0] === 'crop') {isCropSelection = true; }
2864
- if (parent.activeObj.shape && !isCropSelection && parent.activeObj.shape !== 'shape') {
2865
- for (let i: number = 0; i < parent.objColl.length; i++) {
2866
- if (JSON.stringify(parent.activeObj) === JSON.stringify(parent.objColl[i as number])) {
2867
- isActObj = true;
2868
- break;
2869
- }
2870
- }
2871
- if (!isActObj) {
2872
- if (isNullOrUndefined(parent.activeObj.currIndex)) {
2873
- parent.activeObj.currIndex = this.getNewShapeId();
2874
- }
2875
- if (isNullOrUndefined(parent.activeObj.order)) {
2876
- parent.activeObj.order = this.getNewOrder();
2877
- }
2878
- this.updImgRatioForActObj();
2879
- const splitWords: string[] = parent.activeObj.currIndex.split('_');
2880
- let tempObjColl: SelectionPoint[] = parent.objColl.splice(0, parseInt(splitWords[1], 10) - 1);
2881
- tempObjColl.push(extend({}, parent.activeObj, {}, true) as SelectionPoint);
2882
- for (let i: number = 0; i < parent.objColl.length; i++) {
2883
- tempObjColl.push(parent.objColl[i as number]);
2884
- }
2885
- parent.objColl = tempObjColl;
2886
- tempObjColl = []; this.refreshActiveObj();
2887
- this.lowerContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
2888
- parent.notify('draw', { prop: 'redrawImgWithObj', onPropertyChange: false});
2889
- parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.lowerContext}});
2890
- parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.upperContext}});
2891
- parent.currObjType.shape = ''; this.refreshActiveObj();
2892
- if (parent.isCircleCrop) {
2893
- parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
2894
- value: {context: this.lowerContext, isSave: null, isFlip: null}});
2895
- }
2896
- parent.notify('toolbar', { prop: 'destroy-qa-toolbar', onPropertyChange: false});
2897
- if (isNullOrUndefined(isMouseDown)) {
2898
- parent.notify('undo-redo', {prop: 'updateCurrUrc', value: {type: 'ok' }});
2899
- parent.notify('draw', { prop: 'setPrevActObj', onPropertyChange: false, value: { prevActObj: null }});
2900
- }
2901
- }
2902
- }
2903
- }
2904
- }
2905
-
2906
- private getNewShapeId(): string {
2907
- const parent: ImageEditor = this.parent;
2908
- let value: number = parent.objColl.length + 1;
2909
- for (let i: number = 0; i < parent.objColl.length; i++) {
2910
- if (parent.objColl[i as number].currIndex === 'shape_' + value) {
2911
- value++; i = -1;
2912
- }
2913
- }
2914
- return 'shape_' + value;
2915
- }
2916
-
2917
- private getNewOrder(): number {
2918
- const parent: ImageEditor = this.parent;
2919
- this.updateShapeColl();
2920
- let value: number = parent.shapeColl.length + 1;
2921
- for (let i: number = 0; i < parent.shapeColl.length; i++) {
2922
- if (parent.shapeColl[i as number].order === value) {
2923
- value++; i = -1;
2924
- }
2925
- }
2926
- return value;
2927
- }
2928
-
2929
- private getHighestOrder(): number {
2930
- const parent: ImageEditor = this.parent;
2931
- this.updateShapeColl();
2932
- let value: number = 0;
2933
- for (let i: number = 0; i < parent.shapeColl.length; i++) {
2934
- if (parent.shapeColl[i as number].order > value) {
2935
- value = parent.shapeColl[i as number].order;
2936
- }
2937
- }
2938
- return value;
2939
- }
2940
-
2941
- private getLowestOrder(): number {
2942
- const parent: ImageEditor = this.parent;
2943
- this.updateShapeColl();
2944
- let value: number = 1;
2945
- for (let i: number = 0; i < parent.shapeColl.length; i++) {
2946
- if (parent.shapeColl[i as number].order < value) {
2947
- value = parent.shapeColl[i as number].order;
2948
- }
2949
- }
2950
- return value;
2951
- }
2952
-
2953
- private alignTextAreaIntoCanvas(): void {
2954
- const parent: ImageEditor = this.parent; const letters: string = parent.textArea.value;
2955
- parent.textArea.value = '';
2956
- for (let i: number = 0, len: number = letters.length; i < len; i++) {
2957
- parent.textArea.value += letters[i as number]; parent.textArea.style.height = 'auto';
2958
- parent.textArea.style.height = parent.textArea.scrollHeight + 'px'; this.setTextBoxWidth();
2959
- }
2960
- }
2961
-
2962
- private transformTextArea(): void {
2963
- const parent: ImageEditor = this.parent;
2964
- if (parent.activeObj.shape === 'text') {
2965
- parent.textArea.style.transformOrigin = '0 0';
2966
- const rotatedDegree: number = parent.activeObj.rotatedAngle * (180 / Math.PI);
2967
- let scale: string = ''; let degree: number = this.getRotDegOfShape(parent.activeObj);
2968
- if (parent.activeObj.flipObjColl.length > 0) {
2969
- for (let i: number = 0; i < parent.activeObj.flipObjColl.length; i++) {
2970
- if (degree !== 0 && degree % 90 === 0 && degree !== 180) {
2971
- scale += parent.activeObj.flipObjColl[i as number].toLowerCase() === 'horizontal' ? 'scale(1, -1)' :
2972
- 'scale(-1, 1)';
2973
- } else {
2974
- scale += parent.activeObj.flipObjColl[i as number].toLowerCase() === 'horizontal' ? 'scale(-1, 1)' :
2975
- 'scale(1, -1)';
2976
- }
2977
- degree += rotatedDegree;
2978
- if (parent.activeObj.flipObjColl[i as number].toLowerCase() === 'horizontal') {
2979
- parent.textArea.style.transform = 'rotate(' + degree + 'deg)' + scale;
2980
- } else if (parent.activeObj.flipObjColl[i as number].toLowerCase() === 'vertical') {
2981
- parent.textArea.style.transform = 'rotate(' + degree + 'deg)' + scale;
2982
- }
2983
- }
2984
- } else {
2985
- degree += rotatedDegree; parent.textArea.style.transform = 'rotate(' + degree + 'deg)';
2986
- }
2987
- }
2988
- }
2989
-
2990
- private getTextAreaWidth(item: string): number {
2991
- const parent: ImageEditor = this.parent;
2992
- const textSettings: TextSettings = parent.activeObj.textSettings;
2993
- const tempBold: boolean = textSettings.bold;
2994
- const tempItalic: boolean = textSettings.italic;
2995
- const tempUnderline: boolean = textSettings.underline;
2996
- const tempStrikethrough: boolean = textSettings.strikethrough;
2997
- switch (item) {
2998
- case 'default':
2999
- textSettings.bold = false;
3000
- textSettings.italic = false;
3001
- textSettings.underline = false;
3002
- textSettings.strikethrough = false;
3003
- break;
3004
- case 'bold':
3005
- textSettings.bold = true;
3006
- textSettings.italic = false;
3007
- textSettings.underline = false;
3008
- textSettings.strikethrough = false;
3009
- break;
3010
- case 'italic':
3011
- textSettings.bold = false;
3012
- textSettings.italic = true;
3013
- textSettings.underline = false;
3014
- textSettings.strikethrough = false;
3015
- break;
3016
- case 'bolditalic':
3017
- textSettings.bold = true;
3018
- textSettings.italic = true;
3019
- textSettings.underline = false;
3020
- textSettings.strikethrough = false;
3021
- break;
3022
- case 'underline':
3023
- textSettings.bold = false;
3024
- textSettings.italic = false;
3025
- textSettings.underline = true;
3026
- textSettings.strikethrough = false;
3027
- break;
3028
- case 'boldunderline':
3029
- textSettings.bold = true;
3030
- textSettings.italic = false;
3031
- textSettings.underline = true;
3032
- textSettings.strikethrough = false;
3033
- break;
3034
- case 'italicunderline':
3035
- textSettings.bold = false;
3036
- textSettings.italic = true;
3037
- textSettings.underline = true;
3038
- textSettings.strikethrough = false;
3039
- break;
3040
- case 'bolditalicunderline':
3041
- textSettings.bold = true;
3042
- textSettings.italic = true;
3043
- textSettings.underline = true;
3044
- textSettings.strikethrough = false;
3045
- break;
3046
- case 'strikethrough':
3047
- textSettings.bold = false;
3048
- textSettings.italic = false;
3049
- textSettings.underline = false;
3050
- textSettings.strikethrough = true;
3051
- break;
3052
- case 'boldstrikethrough':
3053
- textSettings.bold = true;
3054
- textSettings.italic = false;
3055
- textSettings.underline = false;
3056
- textSettings.strikethrough = true;
3057
- break;
3058
- case 'italicstrikethrough':
3059
- textSettings.bold = false;
3060
- textSettings.italic = true;
3061
- textSettings.underline = false;
3062
- textSettings.strikethrough = true;
3063
- break;
3064
- case 'underlinestrikethrough':
3065
- textSettings.bold = false;
3066
- textSettings.italic = false;
3067
- textSettings.underline = true;
3068
- textSettings.strikethrough = true;
3069
- break;
3070
- case 'bolditalicstrikethrough':
3071
- textSettings.bold = true;
3072
- textSettings.italic = true;
3073
- textSettings.underline = false;
3074
- textSettings.strikethrough = true;
3075
- break;
3076
- case 'boldunderlinestrikethrough':
3077
- textSettings.bold = true;
3078
- textSettings.italic = false;
3079
- textSettings.underline = true;
3080
- textSettings.strikethrough = true;
3081
- break;
3082
- case 'italicunderlinestrikethrough':
3083
- textSettings.bold = false;
3084
- textSettings.italic = true;
3085
- textSettings.underline = true;
3086
- textSettings.strikethrough = true;
3087
- break;
3088
- case 'bolditalicunderlinestrikethrough':
3089
- textSettings.bold = true;
3090
- textSettings.italic = true;
3091
- textSettings.underline = true;
3092
- textSettings.strikethrough = true;
3093
- break;
3094
- }
3095
- const isTextArea: boolean = parent.textArea.style.display === 'none' ? false : true;
3096
- this.updateFontStyles(isTextArea); let width: number;
3097
- if (!isTextArea) {
3098
- width = this.upperContext.measureText(parent.activeObj.keyHistory).width +
3099
- textSettings.fontSize * 0.5;
3100
- } else {
3101
- width = this.upperContext.measureText(parent.textArea.value).width +
3102
- textSettings.fontSize * 0.5;
3103
- }
3104
- textSettings.bold = tempBold; textSettings.italic = tempItalic;
3105
- textSettings.underline = tempUnderline; textSettings.strikethrough = tempStrikethrough;
3106
- return width;
3107
- }
3108
-
3109
- private getRedactObjDetails(obj: SelectionPoint): RedactSettings {
3110
- const parent: ImageEditor = this.parent;
3111
- const redactDetails: RedactSettings = {} as RedactSettings; redactDetails.id = obj.currIndex;
3112
- redactDetails.type = parent.toPascalCase(obj.redactType) as RedactType;
3113
- redactDetails.startX = obj.activePoint.startX; redactDetails.startY = obj.activePoint.startY;
3114
- redactDetails.width = obj.activePoint.width; redactDetails.height = obj.activePoint.height;
3115
- switch (obj.redactType) {
3116
- case 'blur':
3117
- redactDetails.blurIntensity = obj.redactBlur;
3118
- break;
3119
- case 'pixelate':
3120
- redactDetails.pixelSize = obj.redactPixelate;
3121
- break;
3122
- }
3123
- return redactDetails;
3124
- }
3125
-
3126
- private getObjDetails(obj: SelectionPoint): ShapeSettings {
3127
- const parent: ImageEditor = this.parent;
3128
- const shapeDetails: ShapeSettings = {} as ShapeSettings; shapeDetails.id = obj.currIndex;
3129
- shapeDetails.type = parent.toPascalCase(obj.shape) as ShapeType;
3130
- shapeDetails.startX = obj.activePoint.startX; shapeDetails.startY = obj.activePoint.startY;
3131
- shapeDetails.index = obj.order;
3132
- const transformObj: Object = {coll: null };
3133
- switch (obj.shape) {
3134
- case 'rectangle':
3135
- shapeDetails.width = obj.activePoint.width;
3136
- shapeDetails.height = obj.activePoint.height;
3137
- shapeDetails.strokeColor = obj.strokeSettings.strokeColor;
3138
- shapeDetails.fillColor = obj.strokeSettings.fillColor;
3139
- shapeDetails.strokeWidth = obj.strokeSettings.strokeWidth;
3140
- shapeDetails.degree = obj.rotatedAngle * (180 / Math.PI);
3141
- break;
3142
- case 'ellipse':
3143
- shapeDetails.radius = obj.activePoint.width / 2;
3144
- shapeDetails.strokeColor = obj.strokeSettings.strokeColor;
3145
- shapeDetails.fillColor = obj.strokeSettings.fillColor;
3146
- shapeDetails.strokeWidth = obj.strokeSettings.strokeWidth;
3147
- shapeDetails.radiusX = obj.activePoint.width / 2;
3148
- shapeDetails.radiusY = obj.activePoint.height / 2;
3149
- shapeDetails.degree = obj.rotatedAngle * (180 / Math.PI);
3150
- break;
3151
- case 'line':
3152
- case 'arrow':
3153
- shapeDetails.length = obj.activePoint.width;
3154
- shapeDetails.strokeColor = obj.strokeSettings.strokeColor;
3155
- shapeDetails.strokeWidth = obj.strokeSettings.strokeWidth;
3156
- shapeDetails.endX = obj.activePoint.endX;
3157
- shapeDetails.endY = obj.activePoint.endY;
3158
- if (obj.shape === 'arrow') {
3159
- const arrowObj: Object = {type: null };
3160
- parent.notify('selection', {prop: 'getArrowType', onPropertyChange: false, value: {type: obj.start, obj: arrowObj}});
3161
- shapeDetails.arrowHead = arrowObj['type'];
3162
- parent.notify('selection', {prop: 'getArrowType', onPropertyChange: false, value: {type: obj.end, obj: arrowObj}});
3163
- shapeDetails.arrowTail = arrowObj['type'];
3164
- }
3165
- break;
3166
- case 'text':
3167
- shapeDetails.text = obj.keyHistory;
3168
- shapeDetails.fontSize = obj.textSettings.fontSize;
3169
- shapeDetails.fontFamily = obj.textSettings.fontFamily;
3170
- shapeDetails.color = obj.strokeSettings.strokeColor;
3171
- shapeDetails.strokeColor = obj.strokeSettings.outlineColor;
3172
- shapeDetails.fillColor = obj.strokeSettings.fillColor;
3173
- shapeDetails.strokeWidth = obj.strokeSettings.outlineWidth;
3174
- shapeDetails.fontStyle = [];
3175
- if (obj.textSettings.bold) {shapeDetails.fontStyle.push('bold'); }
3176
- if (obj.textSettings.italic) {shapeDetails.fontStyle.push('italic'); }
3177
- if (obj.textSettings.underline) {shapeDetails.fontStyle.push('underline'); }
3178
- if (obj.textSettings.strikethrough) {shapeDetails.fontStyle.push('strikethrough'); }
3179
- shapeDetails.degree = obj.rotatedAngle * (180 / Math.PI);
3180
- parent.notify('selection', {prop: 'updateTransColl', onPropertyChange: false, value: {obj: transformObj, object: obj}});
3181
- shapeDetails.transformCollection = transformObj['coll'];
3182
- break;
3183
- case 'path':
3184
- shapeDetails.strokeColor = obj.strokeSettings.strokeColor;
3185
- shapeDetails.strokeWidth = obj.strokeSettings.strokeWidth;
3186
- shapeDetails.points = obj.pointColl;
3187
- break;
3188
- case 'image':
3189
- shapeDetails.imageData = obj.imageCanvas.toDataURL();
3190
- shapeDetails.degree = obj.rotatedAngle * (180 / Math.PI);
3191
- shapeDetails.width = obj.activePoint.width;
3192
- shapeDetails.height = obj.activePoint.height;
3193
- shapeDetails.opacity = obj.opacity;
3194
- break;
3195
- }
3196
- return shapeDetails;
3197
- }
3198
-
3199
- private getFreehandDrawDetails(index: number): ShapeSettings {
3200
- const parent: ImageEditor = this.parent;
3201
- const shapeDetails: ShapeSettings = {} as ShapeSettings;
3202
- shapeDetails.id = parent.pointColl[index as number].id;
3203
- shapeDetails.type = ShapeType.FreehandDraw;
3204
- shapeDetails.points = extend([], parent.pointColl[index as number].points) as Point[];
3205
- shapeDetails.strokeColor = parent.pointColl[index as number].strokeColor;
3206
- shapeDetails.strokeWidth = parent.pointColl[index as number].strokeWidth;
3207
- shapeDetails.index = parent.pointColl[index as number].order;
3208
- return shapeDetails;
3209
- }
3210
-
3211
- private getShapeSetting(id: string, obj: Object): void {
3212
- const parent: ImageEditor = this.parent; let shapeDetails: ShapeSettings;
3213
- if (!parent.disabled && parent.isImageLoaded) {
3214
- if (parent.textArea.style.display !== 'none') {
3215
- parent.okBtn(null, true);
3216
- } else {
3217
- this.applyActObj(true);
3218
- }
3219
- if (id.split('_')[0] === 'shape') {
3220
- let obj: SelectionPoint;
3221
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
3222
- if (parent.objColl[i as number].currIndex === id) {
3223
- obj = extend({}, parent.objColl[i as number], {}, true) as SelectionPoint;
3224
- break;
3225
- }
3226
- }
3227
- shapeDetails = this.getObjDetails(obj);
3228
- } else if (id.split('_')[0] === 'pen') {
3229
- shapeDetails = this.getFreehandDrawDetails(parseInt(id.split('_')[1], 10) - 1);
3230
- }
3231
- }
3232
- obj['shapeDetails'] = shapeDetails;
3233
- }
3234
-
3235
- private getShapeSettings(obj: Object): void {
3236
- const parent: ImageEditor = this.parent; const shapeDetailsColl: ShapeSettings[] = [];
3237
- if (!parent.disabled && parent.isImageLoaded) {
3238
- if (parent.textArea.style.display !== 'none') {
3239
- parent.okBtn(null, true);
3240
- } else {
3241
- this.applyActObj(true);
3242
- }
3243
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
3244
- const shapeDetails: ShapeSettings = this.getObjDetails(parent.objColl[i as number]);
3245
- shapeDetailsColl.push(shapeDetails);
3246
- }
3247
- for (let i: number = 0; i < parent.freehandCounter; i++) {
3248
- const shapeDetails: ShapeSettings = this.getFreehandDrawDetails(i as number);
3249
- shapeDetailsColl.push(shapeDetails);
3250
- }
3251
- }
3252
- obj['shapeDetailsColl'] = shapeDetailsColl;
3253
- }
3254
-
3255
- private getRedactSettings(obj: Object): void {
3256
- const parent: ImageEditor = this.parent; const RedactDetailsColl: RedactSettings[] = [];
3257
- if (!parent.disabled && parent.isImageLoaded) {
3258
- if (parent.textArea.style.display !== 'none') {
3259
- parent.okBtn(null, true);
3260
- } else {
3261
- this.applyActObj(true);
3262
- }
3263
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
3264
- const redactDetails: RedactSettings = this.getRedactObjDetails(parent.objColl[i as number]);
3265
- RedactDetailsColl.push(redactDetails);
3266
- }
3267
- }
3268
- obj['shapeDetailsColl'] = RedactDetailsColl;
3269
- }
3270
-
3271
- private isPointsInRange(x: number, y: number, obj: Object): void {
3272
- let inRange: boolean = false; const parent: ImageEditor = this.parent;
3273
- if (!isNullOrUndefined(x) && !isNullOrUndefined(y) && x >= parent.img.destLeft && y >= parent.img.destTop &&
3274
- x <= parent.img.destLeft + parent.img.destWidth && y <= parent.img.destTop + parent.img.destHeight) {
3275
- inRange = true;
3276
- }
3277
- obj['inRange'] = inRange;
3278
- }
3279
-
3280
- private alignRotateFlipColl(collection: number[] | string[], isRotateFlipCollection?: boolean,
3281
- obj?: Object): number[] | string[] {
3282
- collection = this.popForDefaultTransformedState(collection);
3283
- collection = this.popForDefaultFlipState(collection);
3284
- collection = this.popForDefaultRotateState(collection);
3285
- if (collection.length === 0 && isRotateFlipCollection) {
3286
- this.parent.transform.degree = 0; this.parent.transform.currFlipState = '';
3287
- }
3288
- obj['collection'] = collection;
3289
- return collection;
3290
- }
3291
-
3292
- private popForDefaultTransformedState(collection: number[] | string[]): number[] | string[] {
3293
- let rotateRight: number = 0; let rotateleft: number = 0; let horizontal: number = 0; let vertical: number = 0;
3294
- for (let i: number = 0; i < collection.length; i++) {
3295
- if (collection[i as number] === 90 || collection[i as number] === 'rotateRight') {
3296
- rotateRight++; rotateleft = 0; horizontal = 0; vertical = 0;
3297
- if (rotateRight === 4) {
3298
- collection.pop(); collection.pop(); collection.pop(); collection.pop();
3299
- }
3300
- } else if (collection[i as number] === -90 || collection[i as number] === 'rotateLeft') {
3301
- rotateleft++; rotateRight = 0; horizontal = 0; vertical = 0;
3302
- if (rotateleft === 4) {
3303
- collection.pop(); collection.pop(); collection.pop(); collection.pop();
3304
- }
3305
- } else if (collection[i as number] === 'horizontal' || collection[i as number] === 'Horizontal'
3306
- || collection[i as number] === 'horizontalflip') {
3307
- horizontal++; rotateleft = 0; rotateRight = 0; vertical = 0;
3308
- if (horizontal === 2) {
3309
- collection.pop(); collection.pop();
3310
- }
3311
- } else if (collection[i as number] === 'vertical' || collection[i as number] === 'Vertical'
3312
- || collection[i as number] === 'verticalflip') {
3313
- vertical++; horizontal = 0; rotateleft = 0; rotateRight = 0;
3314
- if (vertical === 2) {
3315
- collection.pop(); collection.pop();
3316
- }
3317
- }
3318
- }
3319
- return collection;
3320
- }
3321
-
3322
- private popForDefaultFlipState(collection: number[] | string[]): number[] | string[] {
3323
- for (let i: number = 0, iLen: number = collection.length - 3; i < iLen; i++) {
3324
- const isHorizontal: boolean = collection[i as number] === 'horizontal' || collection[i as number] === 'Horizontal'
3325
- || collection[i as number] === 'horizontalFlip';
3326
- const isVertical: boolean = collection[i as number] === 'vertical' || collection[i as number] === 'Vertical' ||
3327
- collection[i as number] === 'verticalFlip';
3328
- const isNextHorizontal: boolean = collection[i + 1] === 'horizontal' || collection[i + 1] === 'Horizontal' ||
3329
- collection[i + 1] === 'horizontalFlip';
3330
- const isNextVertical: boolean = collection[i + 1] === 'vertical' || collection[i + 1] === 'Vertical' ||
3331
- collection[i + 1] === 'verticalFlip';
3332
- const isNextToNextHorizontal: boolean = collection[i + 2] === 'horizontal' || collection[i + 2] === 'Horizontal' ||
3333
- collection[i + 2] === 'horizontalFlip';
3334
- const isNextToNextVertical: boolean = collection[i + 2] === 'vertical' || collection[i + 2] === 'Vertical' ||
3335
- collection[i + 2] === 'verticalFlip';
3336
- const isNextToNextToNextHorizontal: boolean = collection[i + 3] === 'horizontal' || collection[i + 3] === 'Horizontal' ||
3337
- collection[i + 3] === 'horizontalFlip';
3338
- if ((isHorizontal && isNextVertical && isNextToNextHorizontal && isNextToNextVertical) ||
3339
- (isVertical && isNextHorizontal && isNextToNextVertical && isNextToNextToNextHorizontal)) {
3340
- collection.splice(i, 4);
3341
- i -= 4;
3342
- }
3343
- }
3344
- return collection;
3345
- }
3346
-
3347
- private popForDefaultRotateState(collection: number[] | string[]): number[] | string[] {
3348
- for (let i: number = 0; i < collection.length - 1; i++) {
3349
- const curr: number | string = collection[i as number];
3350
- const next: number | string = collection[i + 1];
3351
- if ((curr === 90 || curr === 'rotateRight') && (next === -90 || next === 'rotateLeft')) {
3352
- collection.splice(i, 2);
3353
- i -= 2;
3354
- } else if ((curr === -90 || curr === 'rotateLeft') && (next === 90 || next === 'rotateRight')) {
3355
- collection.splice(i, 2);
3356
- i -= 2;
3357
- }
3358
- }
3359
- return collection;
3360
- }
3361
-
3362
- private selectShape(id: string, obj: Object): void {
3363
- const parent: ImageEditor = this.parent; let isSelected: boolean = false;
3364
- if (!parent.disabled && parent.isImageLoaded) {
3365
- this.applyActObj();
3366
- if (id.split('_')[0] === 'shape') {
3367
- let obj: SelectionPoint;
3368
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
3369
- if (parent.objColl[i as number].currIndex === id) {
3370
- obj = extend({}, parent.objColl[i as number], {}, true) as SelectionPoint;
3371
- break;
3372
- }
3373
- }
3374
- if (isNullOrUndefined(obj)) {isSelected = false; }
3375
- else {
3376
- isSelected = true; parent.activeObj = obj;
3377
- const object: Object = {canvasFilter: null };
3378
- parent.notify('toolbar', { prop: 'getCanvasFilter', onPropertyChange: false, value: {obj: object }});
3379
- this.lowerContext.filter = object['canvasFilter'];
3380
- parent.notify('selection', { prop: 'redrawShape', onPropertyChange: false,
3381
- value: {obj: parent.activeObj}});
3382
- if (parent.activeObj.shape === 'text') {
3383
- parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'text',
3384
- isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
3385
- } else if (parent.activeObj.shape === 'pen') {
3386
- parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'pen',
3387
- isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
3388
- } else if (parent.activeObj.shape === 'redact') {
3389
- parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'redact',
3390
- isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
3391
- } else {
3392
- parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'shapes',
3393
- isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
3394
- }
3395
- parent.notify('toolbar', { prop: 'update-toolbar-items', onPropertyChange: false});
3396
- parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: {isPenEdit: null} });
3397
- }
3398
- } else if (id.split('_')[0] === 'pen') {
3399
- const object: Object = {bool: false };
3400
- parent.notify('selection', { prop: 'getFreehandDrawEditing', onPropertyChange: false, value: {obj: object }});
3401
- if (object['bool']) {parent.okBtn(null, true); }
3402
- const obj: Object = {isIndex: false };
3403
- parent.notify('freehand-draw', { prop: 'isFHDIdx', value: { index: parseInt(id.split('_')[1], 10) - 1, obj: obj }});
3404
- if (obj['isIndex']) {
3405
- isSelected = true;
3406
- parent.notify('freehand-draw', { prop: 'selectFhd', value: { id: id} });
3407
- parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: {isPenEdit: true} });
3408
- parent.notify('toolbar', { prop: 'update-toolbar-items', onPropertyChange: false});
3409
- } else {
3410
- isSelected = false;
3411
- }
3412
- }
3413
- }
3414
- obj['isSelected'] = isSelected;
3415
- }
3416
-
3417
- private deleteShape(id: string): void {
3418
- const parent: ImageEditor = this.parent;
3419
- if (!parent.disabled && parent.isImageLoaded) {
3420
- if (parent.activeObj.currIndex && parent.activeObj.currIndex === id) {
3421
- parent.notify('selection', { prop: 'deleteItem', onPropertyChange: false});
3422
- } else {
3423
- this.applyActObj();
3424
- if (id.split('_')[0] === 'shape') {
3425
- for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
3426
- if (parent.objColl[i as number].currIndex === id) {
3427
- parent.objColl.splice(i, 1);
3428
- break;
3429
- }
3430
- }
3431
- } else if (id.split('_')[0] === 'pen') {
3432
- parent.notify('freehand-draw', {prop: 'handle-freehand-draw', value: {id: id}});
3433
- }
3434
- }
3435
- const object: Object = {canvasFilter: null };
3436
- parent.notify('toolbar', { prop: 'getCanvasFilter', onPropertyChange: false, value: {obj: object }});
3437
- this.lowerContext.filter = object['canvasFilter'];
3438
- this.lowerContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
3439
- parent.notify('draw', { prop: 'redrawImgWithObj', onPropertyChange: false});
3440
- parent.notify('toolbar', { prop: 'refresh-main-toolbar', onPropertyChange: false});
3441
- parent.notify('undo-redo', {prop: 'updateCurrUrc', value: {type: 'ok' }});
3442
- }
3443
- }
3444
-
3445
- private getMaxText(isTextBox?: boolean, text?: string, obj?: Object): string {
3446
- if (isNullOrUndefined(text)) {
3447
- text = isTextBox ? this.parent.textArea.value : this.parent.activeObj.keyHistory;
3448
- if (!text) {return text; }
3449
- }
3450
- let maxi: number; const rows: string[] = text.split('\n'); let maxStr: number = rows[0].length;
3451
- let maxText: string = rows[0];
3452
- for (let i: number = 1; i < rows.length; i++) {
3453
- maxi = rows[i as number].length;
3454
- if (maxi > maxStr) {
3455
- maxText = rows[i as number]; maxStr = maxi;
3456
- }
3457
- }
3458
- if (obj) { obj['maxText'] = maxText; }
3459
- return maxText;
3460
- }
3461
- private getLinePoints(x1: number, y1: number, x2: number, y2: number): Point[] {
3462
- let points: Point[] = []; let i: number[]; let j: number[];
3463
- if (x1 === x2) {
3464
- if (y1 < y2) {
3465
- i = [x1, y1]; j = [x2, y2];
3466
- } else {
3467
- j = [x1, y1]; i = [x2, y2];
3468
- }
3469
- const m: number = this.getSlope(i, j, true); const b: number = this.getIntercept(i, m);
3470
- for (let y: number = i[1]; y <= j[1]; y++){
3471
- const x: number = m * y + b; points.push({x: x, y: y});
3472
- }
3473
- } else {
3474
- if (x1 < x2) {
3475
- i = [x1, y1]; j = [x2, y2];
3476
- } else {
3477
- j = [x1, y1]; i = [x2, y2];
3478
- }
3479
- const m: number = this.getSlope(i, j, false); const b: number = this.getIntercept(i, m);
3480
- for (let x: number = i[0]; x <= j[0]; x++){
3481
- const y: number = m * x + b; points.push({x: x, y: y});
3482
- }
3483
- }
3484
- if (Math.floor(x1) === Math.floor(x2) || (points.length < 10 && (y2 - y1 > 10 || y1 - y2 > 10))) {
3485
- points = [];
3486
- const lesserY: number = Math.min(y1, y2);
3487
- for (let i: number = 0; i < Math.abs(Math.floor(y2) - Math.floor(y1)); i++) {
3488
- points.push({x: x1, y: lesserY + i});
3489
- }
3490
- if (points.length > 1) {
3491
- let prev: Point;
3492
- if (isNullOrUndefined(points[points.length - 2])) {prev = {x: 0, y: 0}; }
3493
- else {prev = points[points.length - 2]; }
3494
- const diffX: number = points[points.length - 1]['x'] - prev.x;
3495
- const diffY: number = points[points.length - 1]['y'] - prev.y;
3496
- points.push({ x: points[points.length - 1]['x'] + (diffX / 2), y: points[points.length - 1]['y'] + (diffY / 2) });
3497
- }
3498
- } else if (Math.floor(y1) === Math.floor(y2) || (points.length < 10 && (x2 - x1 > 10 || x1 - x2 > 10))) {
3499
- points = [];
3500
- const lesserX: number = Math.min(x1, x2);
3501
- for (let i: number = 0; i < Math.abs(Math.floor(x2) - Math.floor(x1)); i++) {
3502
- points.push({x: lesserX + i, y: y1});
3503
- }
3504
- if (points.length > 1) {
3505
- let prev: Point;
3506
- if (isNullOrUndefined(points[points.length - 2])) {prev = {x: 0, y: 0}; }
3507
- else {prev = points[points.length - 2]; }
3508
- const diffX: number = points[points.length - 1]['x'] - prev.x;
3509
- const diffY: number = points[points.length - 1]['y'] - prev.y;
3510
- points.push({ x: points[points.length - 1]['x'] + (diffX / 2), y: points[points.length - 1]['y'] + (diffY / 2) });
3511
- }
3512
- }
3513
- return points;
3514
- }
3515
-
3516
- private getSlope(a: number[], b: number[], isSameAxis: boolean): number {
3517
- let slope: number;
3518
- if (isSameAxis) {
3519
- if (a[1] === b[1]) {return null; } slope = (b[0] - a[0]) / (b[1] - a[1]);
3520
- } else {
3521
- if (a[0] === b[0]) {return null; } slope = (b[1] - a[1]) / (b[0] - a[0]);
3522
- }
3523
- return slope;
3524
- }
3525
-
3526
- private getIntercept(point: number[], getSlope: number): number {
3527
- if (getSlope === null) {return point[0]; }
3528
- return point[1] - getSlope * point[0];
3529
- }
3530
-
3531
- private setPointCollForShapeRotation(obj: SelectionPoint): void {
3532
- const parent: ImageEditor = this.parent;
3533
- const { startX, startY, endX, endY, width, height } = obj.activePoint;
3534
- const center: Point = {x: startX + (width / 2), y: startY +
3535
- (height / 2)};
3536
- const cosAngle: number = Math.cos(obj.rotatedAngle);
3537
- const sinAngle: number = Math.sin(obj.rotatedAngle);
3538
- const p1: Point = { x: cosAngle * (startX - center.x) - sinAngle * (startY - center.y) + center.x,
3539
- y: sinAngle * (startX - center.x) + cosAngle * (startY - center.y) + center.y };
3540
- const p2: Point = { x: cosAngle * (endX - center.x) - sinAngle * (startY - center.y) + center.x,
3541
- y: sinAngle * (endX - center.x) + cosAngle * (startY - center.y) + center.y };
3542
- const p3: Point = { x: cosAngle * (startX - center.x) - sinAngle * (endY - center.y) + center.x,
3543
- y: sinAngle * (startX - center.x) + cosAngle * (endY - center.y) + center.y };
3544
- const p4: Point = { x: cosAngle * (endX - center.x) - sinAngle * (endY - center.y) + center.x,
3545
- y: sinAngle * (endX - center.x) + cosAngle * (endY - center.y) + center.y };
3546
- obj.horTopLinePointColl = this.getLinePoints(p1.x, p1.y, p2.x, p2.y);
3547
- obj.horTopLinePointColl = this.getLinePoints(p1.x, p1.y, p2.x, p2.y);
3548
- obj.horBottomLinePointColl = this.getLinePoints(p3.x, p3.y, p4.x, p4.y);
3549
- obj.verLeftLinePointColl = this.getLinePoints(p1.x, p1.y, p3.x, p3.y);
3550
- obj.verRightLinePointColl = this.getLinePoints(p2.x, p2.y, p4.x, p4.y);
3551
- obj.verLeftLinePointColl.reverse(); obj.verRightLinePointColl.reverse();
3552
- for (let i: number = 0; i < obj.horTopLinePointColl.length; i++) {
3553
- obj.horTopLinePointColl[i as number].ratioX = (obj.horTopLinePointColl[i as number].x -
3554
- this.parent.img.destLeft) / this.parent.img.destWidth;
3555
- obj.horTopLinePointColl[i as number].ratioY = (obj.horTopLinePointColl[i as number].y -
3556
- this.parent.img.destTop) / this.parent.img.destHeight;
3557
- }
3558
- for (let i: number = 0; i < obj.horBottomLinePointColl.length; i++) {
3559
- obj.horBottomLinePointColl[i as number].ratioX = (obj.horBottomLinePointColl[i as number].x -
3560
- this.parent.img.destLeft) / this.parent.img.destWidth;
3561
- obj.horBottomLinePointColl[i as number].ratioY = (obj.horBottomLinePointColl[i as number].y -
3562
- this.parent.img.destTop) / this.parent.img.destHeight;
3563
- }
3564
- for (let i: number = 0; i < obj.verLeftLinePointColl.length; i++) {
3565
- obj.verLeftLinePointColl[i as number].ratioX = (obj.verLeftLinePointColl[i as number].x -
3566
- this.parent.img.destLeft) / this.parent.img.destWidth;
3567
- obj.verLeftLinePointColl[i as number].ratioY = (obj.verLeftLinePointColl[i as number].y -
3568
- this.parent.img.destTop) / this.parent.img.destHeight;
3569
- }
3570
- for (let i: number = 0; i < obj.verRightLinePointColl.length; i++) {
3571
- obj.verRightLinePointColl[i as number].ratioX = (obj.verRightLinePointColl[i as number].x -
3572
- this.parent.img.destLeft) / this.parent.img.destWidth;
3573
- obj.verRightLinePointColl[i as number].ratioY = (obj.verRightLinePointColl[i as number].y -
3574
- this.parent.img.destTop) / this.parent.img.destHeight;
3575
- }
3576
- if (parent.upperCanvas.style.cursor !== 'move') {
3577
- const object: Object = {rotationCirclePoint: null };
3578
- parent.notify('selection', { prop: 'getTransRotationPoint', value: {obj: obj, object: object }});
3579
- const rotationCirclePoint: Point = object['rotationCirclePoint'];
3580
- if (rotationCirclePoint) {
3581
- obj.rotationCirclePointColl = { x: cosAngle * (rotationCirclePoint.x - center.x) -
3582
- sinAngle * (rotationCirclePoint.y - center.y) + center.x,
3583
- y: sinAngle * (rotationCirclePoint.x - center.x) + cosAngle
3584
- * (rotationCirclePoint.y - center.y) + center.y };
3585
- obj.rotationCirclePointColl.ratioX = (obj.rotationCirclePointColl.x - parent.img.destLeft) /
3586
- parent.img.destWidth;
3587
- obj.rotationCirclePointColl.ratioY = (obj.rotationCirclePointColl.y - parent.img.destTop) /
3588
- parent.img.destHeight;
3589
- }
3590
- }
3591
- }
3592
-
3593
- private getSquarePointForRotatedShape(obj: SelectionPoint, object?: Object): ActivePoint {
3594
- const point: ActivePoint = { startX: 0, startY: 0, endX: 0, endY: 0, width: 0, height: 0 };
3595
- const { startX, startY, endX, endY, width, height } = obj.activePoint;
3596
- const center: Point = {x: startX + (width / 2), y: startY + (height / 2)};
3597
- const cosAngle: number = Math.cos(obj.rotatedAngle);
3598
- const sinAngle: number = Math.sin(obj.rotatedAngle);
3599
- const p1: Point = { x: cosAngle * (startX - center.x) - sinAngle * (startY - center.y) + center.x,
3600
- y: sinAngle * (startX - center.x) + cosAngle * (startY - center.y) + center.y };
3601
- const p2: Point = { x: cosAngle * (endX - center.x) - sinAngle * (startY - center.y) + center.x,
3602
- y: sinAngle * (endX - center.x) + cosAngle * (startY - center.y) + center.y };
3603
- const p3: Point = { x: cosAngle * (startX - center.x) - sinAngle * (endY - center.y) + center.x,
3604
- y: sinAngle * (startX - center.x) + cosAngle * (endY - center.y) + center.y };
3605
- const p4: Point = { x: cosAngle * (endX - center.x) - sinAngle * (endY - center.y) + center.x,
3606
- y: sinAngle * (endX - center.x) + cosAngle * (endY - center.y) + center.y };
3607
- point.startX = p1.x; point.startY = p1.y; point.endX = p1.x; point.endY = p1.y;
3608
- if (point.startX > p2.x) { point.startX = p2.x; } if (point.startX > p3.x) { point.startX = p3.x; }
3609
- if (point.startX > p4.x) { point.startX = p4.x; } if (point.startY > p2.y) { point.startY = p2.y; }
3610
- if (point.startY > p3.y) { point.startY = p3.y; } if (point.startY > p4.y) { point.startY = p4.y; }
3611
- if (point.endX < p2.x) { point.endX = p2.x; } if (point.endX < p3.x) { point.endX = p3.x; }
3612
- if (point.endX < p4.x) { point.endX = p4.x; } if (point.endY < p2.y) { point.endY = p2.y; }
3613
- if (point.endY < p3.y) { point.endY = p3.y; } if (point.endY < p4.y) { point.endY = p4.y; }
3614
- point.width = point.endX - point.startX; point.height = point.endY - point.startY;
3615
- if (object) {
3616
- object['activePoint'] = point;
3617
- }
3618
- return point;
3619
- }
3620
-
3621
- private updateZOrder(obj: SelectionPoint | Object, value: string): void {
3622
- const parent: ImageEditor = this.parent;
3623
- value = value.toLowerCase();
3624
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3625
- const object: any = obj;
3626
- if (isNullOrUndefined(object.order)) {return; }
3627
- let index: number; let prevIndex: number;
3628
- const highestOrder: number = this.getHighestOrder();
3629
- this.updateShapeColl();
3630
- if (parent.shapeColl.length === 0) {
3631
- return;
3632
- }
3633
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3634
- let coll: any;
3635
- for (let i: number = 0; i < parent.shapeColl.length; i++) {
3636
- coll = parent.shapeColl[i as number];
3637
- if (object.id && object.id.indexOf('pen') > -1) {
3638
- if (coll.id && coll.id === object.id) {
3639
- parent.shapeColl.splice(i, 1);
3640
- }
3641
- } else if (coll.shape && coll.shape.indexOf('crop-') > -1) {
3642
- parent.shapeColl.splice(i, 1);
3643
- }
3644
- }
3645
- switch (value) {
3646
- case 'sendtoback':
3647
- prevIndex = object.order;
3648
- index = object.order;
3649
- object.order = 1;
3650
- break;
3651
- case 'sendbackward':
3652
- object.order -= 1;
3653
- index = object.order;
3654
- break;
3655
- case 'bringtofront':
3656
- prevIndex = object.order;
3657
- index = highestOrder;
3658
- object.order = index;
3659
- break;
3660
- case 'bringforward':
3661
- object.order += 1;
3662
- index = object.order;
3663
- break;
3664
- }
3665
- this.reArrangeObjColl(index, value, prevIndex);
3666
- if (object.id && object.id.indexOf('pen') > -1) {
3667
- this.reUpdateShapeColl(object);
3668
- }
3669
- }
3670
-
3671
- private reArrangeObjColl(index: number, value: string, prevIndex: number): void {
3672
- const parent: ImageEditor = this.parent;
3673
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3674
- let obj: any;
3675
- switch (value) {
3676
- case 'sendtoback':
3677
- for (let i: number = 0, len: number = parent.shapeColl.length; i < len; i++) {
3678
- obj = parent.shapeColl[i as number];
3679
- if (obj.order < prevIndex && obj.order <= index) {
3680
- obj.order += 1;
3681
- this.reUpdateShapeColl(obj);
3682
- }
3683
- }
3684
- break;
3685
- case 'sendbackward':
3686
- for (let i: number = 0, len: number = parent.shapeColl.length; i < len; i++) {
3687
- obj = parent.shapeColl[i as number];
3688
- if (obj.order === index) {
3689
- obj.order += 1;
3690
- this.reUpdateShapeColl(obj);
3691
- break;
3692
- }
3693
- }
3694
- break;
3695
- case 'bringtofront':
3696
- for (let i: number = 0, len: number = parent.shapeColl.length; i < len; i++) {
3697
- obj = parent.shapeColl[i as number];
3698
- if (obj.order > prevIndex && obj.order <= index) {
3699
- obj.order -= 1;
3700
- this.reUpdateShapeColl(obj);
3701
- }
3702
- }
3703
- break;
3704
- case 'bringforward':
3705
- for (let i: number = 0, len: number = parent.shapeColl.length; i < len; i++) {
3706
- obj = parent.shapeColl[i as number];
3707
- if (obj.order === index) {
3708
- obj.order -= 1;
3709
- this.reUpdateShapeColl(obj);
3710
- break;
3711
- }
3712
- }
3713
- break;
3714
- }
3715
- }
3716
-
3717
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3718
- private reorderRedact(tempObjColl: SelectionPoint[] | any): SelectionPoint[] | any {
3719
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3720
- const nonRedact: any = tempObjColl.filter((item: SelectionPoint) => item.shape !== 'redact');
3721
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3722
- const redact: any = tempObjColl.filter((item: SelectionPoint) => item.shape === 'redact');
3723
- return redact.concat(nonRedact);
3724
- }
3725
-
3726
- private updateShapeColl(): void {
3727
- const parent: ImageEditor = this.parent;
3728
- let isOrdered: boolean = false; let tempOrder: number = 1;
3729
- let tempObjColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
3730
- tempObjColl = this.reorderRedact(tempObjColl);
3731
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3732
- let tempPointColl: any = extend([], parent.pointColl, [], true);
3733
- if (parent.shapeColl.length > 0 &&
3734
- parent.shapeColl.length === parent.objColl.length + parent.pointColl.length) {
3735
- for (let i: number = 0; i < parent.shapeColl.length; i++) {
3736
- if (parent.shapeColl[i as number].order === tempOrder) {
3737
- isOrdered = true; tempOrder++;
3738
- } else {
3739
- isOrdered = false;
3740
- break;
3741
- }
3742
- }
3743
- if (isOrdered) {
3744
- for (let i: number = 0; i < parent.shapeColl.length; i++) {
3745
- if (parent.shapeColl[i as number].currIndex &&
3746
- parent.shapeColl[i as number].currIndex.indexOf('shape') > -1) {
3747
- for (let j: number = 0; j < tempObjColl.length; j++) {
3748
- if (parent.shapeColl[i as number].currIndex === tempObjColl[j as number].currIndex) {
3749
- parent.shapeColl[i as number] = extend({}, tempObjColl[j as number], {}, true);
3750
- tempObjColl.splice(j, 1);
3751
- break;
3752
- }
3753
- }
3754
- } else if (parent.shapeColl[i as number].id && parent.shapeColl[i as number].id.indexOf('pen') > -1) {
3755
- for (let j: number = 0; j < tempPointColl.length; j++) {
3756
- if (parent.shapeColl[i as number].id === tempPointColl[j as number].id) {
3757
- parent.shapeColl[i as number] = extend([], tempPointColl[j as number], [], true);
3758
- tempPointColl.splice(j, 1);
3759
- break;
3760
- }
3761
- }
3762
- }
3763
- }
3764
- return;
3765
- }
3766
- }
3767
- tempObjColl = extend([], parent.objColl, [], true) as SelectionPoint[];
3768
- tempPointColl = extend([], parent.pointColl, [], true);
3769
- parent.shapeColl = []; let order: number = 1; let isBreak: boolean; let isCrop: boolean = false;
3770
- while (tempObjColl.length !== 0 || tempPointColl.length !== 0) {
3771
- isBreak = isCrop = false;
3772
- for (let i: number = 0; i < tempObjColl.length; i++) {
3773
- if (tempObjColl[i as number].order === order ||
3774
- (!tempObjColl[i as number].order && tempObjColl[i as number].shape &&
3775
- tempObjColl[i as number].shape.indexOf('crop-') > -1)) {
3776
- parent.shapeColl.push(extend({}, tempObjColl[i as number], {}, true));
3777
- if (tempObjColl[i as number].shape && tempObjColl[i as number].shape.indexOf('crop-') > -1) {
3778
- isCrop = true;
3779
- }
3780
- tempObjColl.splice(i, 1);
3781
- isBreak = true;
3782
- break;
3783
- }
3784
- }
3785
- if (!isBreak) {
3786
- for (let i: number = 0; i < tempPointColl.length; i++) {
3787
- if (tempPointColl[i as number].order === order) {
3788
- parent.shapeColl.push(extend([], tempPointColl[i as number], [], true));
3789
- tempPointColl.splice(i, 1);
3790
- isBreak = true;
3791
- break;
3792
- }
3793
- }
3794
- }
3795
- if (!isCrop) {order++; }
3796
- }
3797
- }
3798
-
3799
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3800
- private reUpdateShapeColl(obj: any): void {
3801
- const parent: ImageEditor = this.parent;
3802
- if (obj.id && obj.id.indexOf('pen') > -1) {
3803
- if (parent.freehandCounter > 0) {
3804
- for (let i: number = 0; i < parent.freehandCounter; i++) {
3805
- if (parent.pointColl[i as number].id === obj.id) {
3806
- parent.pointColl[i as number].order = obj.order;
3807
- }
3808
- }
3809
- }
3810
- } else if (obj.currIndex && obj.currIndex.indexOf('shape') > -1) {
3811
- for (let i: number = 0; i < parent.objColl.length; i++) {
3812
- if (parent.objColl[i as number].currIndex === obj.currIndex) {
3813
- parent.objColl[i as number].order = obj.order;
3814
- }
3815
- }
3816
- }
3817
- }
3818
-
3819
- private drawAnnotations(ctx: CanvasRenderingContext2D, shape: string, pen: string, isPreventApply: boolean,
3820
- x: number, y: number, panRegion: string): void {
3821
- const parent: ImageEditor = this.parent;
3822
- const activeObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
3823
- const tempObjColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
3824
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3825
- const tempPointColl: any = extend([], parent.pointColl, [], true);
3826
- const tempSelPointCollObj: Object = {selPointColl: null };
3827
- parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
3828
- value: {obj: tempSelPointCollObj }});
3829
- const selPointCollObj: Object = {selPointColl: null };
3830
- parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
3831
- value: {obj: selPointCollObj }});
3832
- this.updateShapeColl();
3833
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3834
- let tempShapeColl: any = extend([], parent.shapeColl, [], true);
3835
- tempShapeColl = this.reorderRedact(tempShapeColl);
3836
- let isPrevented: boolean = false;
3837
- if (!this.preventFrameAnnotation) {this.preventFrameAnnotation = isPrevented = true; }
3838
- for (let i: number = 0; i < tempShapeColl.length; i++) {
3839
- const isPenId: string = tempShapeColl[i as number].id;
3840
- if ((tempShapeColl[i as number].order) ||
3841
- (!tempShapeColl[i as number].order && tempShapeColl[i as number].shape && tempShapeColl[i as number].shape.indexOf('crop-') > -1) ||
3842
- (!tempShapeColl[i as number].order && tempShapeColl[i as number].shape === 'path' && parent.drawingShape === 'path')) {
3843
- if (tempShapeColl[i as number].currIndex && tempShapeColl[i as number].currIndex.indexOf('shape') > -1) {
3844
- parent.objColl = [];
3845
- parent.objColl.push(extend({}, tempShapeColl[i as number], {}, true) as SelectionPoint);
3846
- if (shape === 'iterate') {
3847
- const temp: string = this.lowerContext.filter;
3848
- this.lowerContext.filter = 'none';
3849
- this.iterateObjColl();
3850
- this.lowerContext.filter = temp;
3851
- } else if (shape === 'zoom' || shape === 'pan') {
3852
- let tempObjCollIndex: number = -1;
3853
- for (let i: number = 0; i < tempObjColl.length; i++) {
3854
- if (JSON.stringify(tempObjColl[i as number]) === JSON.stringify(parent.objColl[0])) {
3855
- tempObjCollIndex = i;
3856
- break;
3857
- }
3858
- }
3859
- if (shape === 'zoom') {
3860
- this.zoomObjColl(isPreventApply);
3861
- } else {
3862
- this.panObjColl(x, y, panRegion);
3863
- }
3864
- if (tempObjCollIndex > -1) {
3865
- tempObjColl[tempObjCollIndex as number] = extend({}, parent.objColl[0], {}, true) as SelectionPoint;
3866
- }
3867
- }
3868
- } else if (tempShapeColl[i as number].id && tempShapeColl[i as number].id.indexOf('pen') > -1) {
3869
- parent.pointColl = []; parent.freehandCounter = 0;
3870
- parent.notify('freehand-draw', { prop: 'setSelPointColl', onPropertyChange: false, value: {obj: {selPointColl: [] } }});
3871
- parent.pointColl.push(extend({}, tempShapeColl[i as number], {}, true));
3872
- parent.notify('freehand-draw', { prop: 'pushSelPointColl', onPropertyChange: false,
3873
- value: {obj: {selPointColl: selPointCollObj['selPointColl'][i as number] } }});
3874
- parent.freehandCounter = parent.pointColl.length;
3875
- if (pen === 'iterate') {
3876
- parent.notify('freehand-draw', { prop: 'freehandRedraw', onPropertyChange: false,
3877
- value: {context: ctx, points: null} });
3878
- } else if (pen === 'zoom' || pen === 'pan') {
3879
- if (pen === 'zoom') {
3880
- parent.notify('freehand-draw', { prop: 'zoomFHDColl', onPropertyChange: false,
3881
- value: {isPreventApply: isPreventApply}});
3882
- } else {
3883
- parent.notify('freehand-draw', { prop: 'panFHDColl', onPropertyChange: false,
3884
- value: {xDiff: x, yDiff: y, panRegion: panRegion}});
3885
- }
3886
- for (let i: number = 0; i < tempPointColl.length; i++) {
3887
- if (tempPointColl[i as number].id === parent.pointColl[0].id) {
3888
- tempPointColl[i as number] = extend({}, parent.pointColl[0], {}, true);
3889
- break;
3890
- }
3891
- }
3892
- for (let i: number = 0, len: number = tempSelPointCollObj['selPointColl'].length; i < len; i++) {
3893
- if (tempSelPointCollObj['selPointColl'][i as number].id === selPointCollObj['selPointColl'][i as number].id) {
3894
- tempSelPointCollObj['selPointColl'][i as number] = extend({}, selPointCollObj['selPointColl'][i as number], {}, true);
3895
- break;
3896
- }
3897
- }
3898
- }
3899
- }
3900
- } else if ((!tempShapeColl[i as number].shape && !isPenId) ||
3901
- (!tempShapeColl[i as number].currIndex && !isPenId)) {
3902
- tempShapeColl.splice(i, 1);
3903
- }
3904
- }
3905
- if (pen && pen === 'zoom') {
3906
- parent.pointColl = []; parent.freehandCounter = 0;
3907
- parent.notify('freehand-draw', { prop: 'zoomFHDColl', onPropertyChange: false, value: {isPreventApply: isPreventApply}});
3908
- }
3909
- parent.objColl = tempObjColl; parent.pointColl = tempPointColl; parent.freehandCounter = parent.pointColl.length;
3910
- parent.notify('freehand-draw', { prop: 'setSelPointColl', onPropertyChange: false, value: {obj: {selPointColl: tempSelPointCollObj['selPointColl'] } }});
3911
- if (isPrevented && this.preventFrameAnnotation) {
3912
- parent.notify('draw', { prop: 'applyFrame', value: { ctx: this.lowerContext, frame: parent.frameObj.type, preventImg: true } });
3913
- this.preventFrameAnnotation = false;
3914
- }
3915
- parent.activeObj = activeObj;
3916
- }
3917
- }