@syncfusion/ej2-image-editor 30.2.4 → 31.1.17

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 (48) hide show
  1. package/dist/ej2-image-editor.umd.min.js +2 -2
  2. package/dist/ej2-image-editor.umd.min.js.map +1 -1
  3. package/dist/es6/ej2-image-editor.es2015.js +3 -3
  4. package/dist/es6/ej2-image-editor.es2015.js.map +1 -1
  5. package/dist/es6/ej2-image-editor.es5.js +3 -3
  6. package/dist/es6/ej2-image-editor.es5.js.map +1 -1
  7. package/dist/global/ej2-image-editor.min.js +2 -2
  8. package/dist/global/ej2-image-editor.min.js.map +1 -1
  9. package/dist/global/index.d.ts +1 -1
  10. package/dist/ts/image-editor/action/crop.d.ts +44 -0
  11. package/dist/ts/image-editor/action/crop.ts +867 -0
  12. package/dist/ts/image-editor/action/draw.d.ts +187 -0
  13. package/dist/ts/image-editor/action/draw.ts +4924 -0
  14. package/dist/ts/image-editor/action/export.d.ts +29 -0
  15. package/dist/ts/image-editor/action/export.ts +509 -0
  16. package/dist/ts/image-editor/action/filter.d.ts +48 -0
  17. package/dist/ts/image-editor/action/filter.ts +872 -0
  18. package/dist/ts/image-editor/action/freehand-draw.d.ts +68 -0
  19. package/dist/ts/image-editor/action/freehand-draw.ts +1135 -0
  20. package/dist/ts/image-editor/action/index.d.ts +9 -0
  21. package/dist/ts/image-editor/action/index.ts +9 -0
  22. package/dist/ts/image-editor/action/selection.d.ts +178 -0
  23. package/dist/ts/image-editor/action/selection.ts +5241 -0
  24. package/dist/ts/image-editor/action/shape.d.ts +130 -0
  25. package/dist/ts/image-editor/action/shape.ts +3917 -0
  26. package/dist/ts/image-editor/action/transform.d.ts +77 -0
  27. package/dist/ts/image-editor/action/transform.ts +2008 -0
  28. package/dist/ts/image-editor/action/undo-redo.d.ts +52 -0
  29. package/dist/ts/image-editor/action/undo-redo.ts +1169 -0
  30. package/dist/ts/image-editor/base/enum.d.ts +277 -0
  31. package/dist/ts/image-editor/base/enum.ts +288 -0
  32. package/dist/ts/image-editor/base/image-editor-model.d.ts +770 -0
  33. package/dist/ts/image-editor/base/image-editor.d.ts +1928 -0
  34. package/dist/ts/image-editor/base/image-editor.ts +5496 -0
  35. package/dist/ts/image-editor/base/index.d.ts +4 -0
  36. package/dist/ts/image-editor/base/index.ts +4 -0
  37. package/dist/ts/image-editor/base/interface.d.ts +1637 -0
  38. package/dist/ts/image-editor/base/interface.ts +1709 -0
  39. package/dist/ts/image-editor/index.d.ts +3 -0
  40. package/dist/ts/image-editor/index.ts +3 -0
  41. package/dist/ts/image-editor/renderer/index.d.ts +1 -0
  42. package/dist/ts/image-editor/renderer/index.ts +1 -0
  43. package/dist/ts/image-editor/renderer/toolbar.d.ts +171 -0
  44. package/dist/ts/image-editor/renderer/toolbar.ts +6356 -0
  45. package/dist/ts/index.d.ts +4 -0
  46. package/dist/ts/index.ts +4 -0
  47. package/package.json +47 -15
  48. package/src/image-editor/action/undo-redo.js +3 -3
@@ -0,0 +1,2008 @@
1
+ /* eslint-disable prefer-const */
2
+ import { Browser, extend, getComponent, isNullOrUndefined } from '@syncfusion/ej2-base';
3
+ import { ActivePoint, Dimension, NumericTextBox } from '@syncfusion/ej2-inputs';
4
+ import { EditCompleteEventArgs , CurrentObject, Direction, FlipEventArgs, ImageEditor, PanEventArgs, Point, ResizeEventArgs, ShapeType } from '../index';
5
+ import { ImageDimension, RotateEventArgs, SelectionPoint, StrokeSettings, ZoomEventArgs } from '../index';
6
+ import { hideSpinner, showSpinner } from '@syncfusion/ej2-popups';
7
+ import { Toolbar } from '@syncfusion/ej2-navigations';
8
+
9
+ export class Transform {
10
+ private parent: ImageEditor;
11
+ private lowerContext: CanvasRenderingContext2D;
12
+ private upperContext: CanvasRenderingContext2D;
13
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
14
+ private zoomBtnHold: any;
15
+ private tempPanMove: Point; // To store previous pan move point
16
+ private panMove: Point; // To store pan move point
17
+ private isReverseFlip: boolean = false; // True when rotate method is called from iteration
18
+ private disablePan: boolean = false; // auto enable / disable pan while zooming
19
+ private currDestPoint: ActivePoint; // To redraw old image when navigate to crop tab
20
+ private isReverseRotate: boolean = false; // True when rotate method is called from iteration
21
+ private flipColl: string[] = []; // To store flip order
22
+ private transCurrObj: CurrentObject;
23
+ private prevZoomValue: number = 1;
24
+ private tempActiveObj: SelectionPoint; private isShape: boolean;
25
+ private cropDimension: Dimension = { width: 0, height: 0 };
26
+ private isPreventSelect: boolean = false;
27
+ private prevResizeCurrObj: CurrentObject;
28
+ private preventDownScale: boolean = false;
29
+ private resizedImgAngle: number = null;
30
+ private resizeEventCancel: boolean;
31
+
32
+ constructor(parent: ImageEditor) {
33
+ this.parent = parent;
34
+ this.addEventListener();
35
+ }
36
+
37
+ public destroy(): void {
38
+ if (this.parent.isDestroyed) { return; }
39
+ this.removeEventListener();
40
+ }
41
+
42
+ private addEventListener(): void {
43
+ this.parent.on('transform', this.transform, this);
44
+ this.parent.on('destroyed', this.destroy, this);
45
+ }
46
+
47
+ private removeEventListener(): void {
48
+ this.parent.off('transform', this.transform);
49
+ this.parent.off('destroyed', this.destroy);
50
+ }
51
+
52
+ private transform(args?: { onPropertyChange: boolean, prop: string, value?: object }): void {
53
+ this.initTransformPvtVar();
54
+ switch (args.prop) {
55
+ case 'flipImage':
56
+ this.flipImage(args.value['direction']);
57
+ break;
58
+ case 'setDestPointsForFlipState':
59
+ this.setDestPointsForFlipState();
60
+ break;
61
+ case 'zoomAction':
62
+ this.zoomAction(args.value['zoomFactor'], args.value['zoomPoint'], args.value['isResize']);
63
+ break;
64
+ case 'disableZoomOutBtn':
65
+ this.disableZoomOutBtn(args.value['isZoomOut']);
66
+ break;
67
+ case 'rotatedFlip':
68
+ this.rotatedFlip();
69
+ break;
70
+ case 'drawPannedImage':
71
+ this.drawPannedImage(args.value['xDiff'], args.value['yDiff']);
72
+ break;
73
+ case 'drawPannImage':
74
+ this.drawPannImage(args.value['point']);
75
+ break;
76
+ case 'performTransformation':
77
+ this.performTransformation(args.value['text']);
78
+ break;
79
+ case 'updateTransform':
80
+ this.updateTransform(args.value['text']);
81
+ break;
82
+ case 'rotatePan':
83
+ this.rotatePan(args.value['isCropSelection'], args.value['isDefaultZoom']);
84
+ break;
85
+ case 'resetZoom':
86
+ this.resetZoom();
87
+ break;
88
+ case 'pan':
89
+ this.pan(args.value['value'], args.value['x'], args.value['y']);
90
+ break;
91
+ case 'zoom':
92
+ this.zoom(args.value['zoomFactor'], args.value['zoomPoint']);
93
+ break;
94
+ case 'setCurrPanRegion':
95
+ this.setCurrPanRegion(args.value['region'], args.value['type'], args.value['obj']);
96
+ break;
97
+ case 'rotate':
98
+ this.rotate(args.value['degree'], args.value['obj']);
99
+ break;
100
+ case 'flip':
101
+ this.flip(args.value['direction']);
102
+ break;
103
+ case 'update':
104
+ this.update();
105
+ break;
106
+ case 'calcMaxDimension':
107
+ this.calcMaxDimension(args.value['width'], args.value['height'], args.value['obj'], args.value['isImgShape']);
108
+ break;
109
+ case 'getPanMove':
110
+ args.value['obj']['panMove'] = this.panMove;
111
+ break;
112
+ case 'setPanMove':
113
+ this.panMove = args.value['point'];
114
+ break;
115
+ case 'getTempPanMove':
116
+ args.value['obj']['tempPanMove'] = this.tempPanMove;
117
+ break;
118
+ case 'setTempPanMove':
119
+ this.tempPanMove = args.value['point'];
120
+ break;
121
+ case 'setReverseFlip':
122
+ this.isReverseFlip = args.value['isReverseFlip'];
123
+ break;
124
+ case 'setDisablePan':
125
+ this.disablePan = args.value['bool'];
126
+ break;
127
+ case 'setCurrDestinationPoint':
128
+ this.currDestPoint = args.value['point'];
129
+ this.currDestPoint.startX -= this.parent.cropObj.totalPannedPoint.x;
130
+ this.currDestPoint.startY -= this.parent.cropObj.totalPannedPoint.y;
131
+ break;
132
+ case 'setReverseRotate':
133
+ this.isReverseRotate = args.value['bool'];
134
+ break;
135
+ case 'getFlipColl':
136
+ args.value['obj']['flipColl'] = this.flipColl;
137
+ break;
138
+ case 'setFlipColl':
139
+ this.flipColl = args.value['flipColl'];
140
+ break;
141
+ case 'getPreviousZoomValue':
142
+ args.value['obj']['previousZoomValue'] = this.prevZoomValue;
143
+ break;
144
+ case 'setPreviousZoomValue':
145
+ this.prevZoomValue = args.value['previousZoomValue'];
146
+ break;
147
+ case 'getCropDimension':
148
+ args.value['obj']['cropDimension'] = this.cropDimension;
149
+ break;
150
+ case 'setCropDimension':
151
+ this.cropDimension.width = args.value['width']; this.cropDimension.height = args.value['height'];
152
+ break;
153
+ case 'getPreventSelect':
154
+ args.value['obj']['bool'] = this.isPreventSelect;
155
+ break;
156
+ case 'setPreventSelect':
157
+ this.isPreventSelect = args.value['bool'];
158
+ break;
159
+ case 'resizeImage':
160
+ this.resizeImage(args.value['width'], args.value['height']);
161
+ break;
162
+ case 'resizeCrop':
163
+ this.resizeCrop(args.value['width'], args.value['height']);
164
+ break;
165
+ case 'updateResize':
166
+ this.updateResize();
167
+ break;
168
+ case 'resize':
169
+ this.resize(args.value['width'], args.value['height'], args.value['isAspectRatio']);
170
+ break;
171
+ case 'straightenImage':
172
+ this.straightenImage(args.value['degree']);
173
+ break;
174
+ case 'reset':
175
+ this.reset();
176
+ break;
177
+ case 'cropZoom':
178
+ args.value['obj']['maxDimension'] = this.cropZoom(args.value['value'], args.value['selectionObj']);
179
+ break;
180
+ case 'setResizedImgAngle':
181
+ this.resizedImgAngle = args.value['angle'];
182
+ break;
183
+ }
184
+ }
185
+
186
+ public getModuleName(): string {
187
+ return 'transform';
188
+ }
189
+
190
+ private initTransformPvtVar(): void {
191
+ if (this.parent.lowerCanvas) {this.lowerContext = this.parent.lowerCanvas.getContext('2d'); }
192
+ if (this.parent.upperCanvas) {this.upperContext = this.parent.upperCanvas.getContext('2d'); }
193
+ }
194
+
195
+ private reset(): void {
196
+ this.zoomBtnHold = null; this.tempPanMove = null; this.panMove = null; this.disablePan = false;
197
+ this.currDestPoint = null; this.isReverseRotate = false; this.flipColl = []; this.resizedImgAngle = null;
198
+ this.transCurrObj = null; this.prevZoomValue = 1; this.isPreventSelect = this.preventDownScale = false;
199
+ }
200
+
201
+ private rotateImage(degree: number): void {
202
+ const parent: ImageEditor = this.parent;
203
+ const transitionArgs: RotateEventArgs = {cancel: false, previousDegree: parent.transform.degree,
204
+ currentDegree: Math.abs(parent.transform.degree + degree) === 360 ? 0 : parent.transform.degree + degree };
205
+ if (!this.isPreventSelect) {
206
+ parent.trigger('rotating', transitionArgs);
207
+ parent.editCompleteArgs = transitionArgs;
208
+ }
209
+ this.rotateEvent(transitionArgs, degree);
210
+ }
211
+
212
+ private rotateEvent(transitionArgs: RotateEventArgs, degree: number): void {
213
+ const parent: ImageEditor = this.parent;
214
+ if (!transitionArgs.cancel) {
215
+ let prevObj: CurrentObject;
216
+ if (isNullOrUndefined(this.transCurrObj)) {
217
+ const object: Object = {currObj: {} as CurrentObject };
218
+ parent.notify('filter', { prop: 'getCurrentObj', onPropertyChange: false, value: {object: object }});
219
+ prevObj = object['currObj'];
220
+ prevObj.objColl = extend([], parent.objColl, null, true) as SelectionPoint[];
221
+ prevObj.pointColl = extend({}, parent.pointColl, null, true) as Point[];
222
+ prevObj.afterCropActions = extend([], parent.afterCropActions, [], true) as string[];
223
+ const selPointCollObj: Object = {selPointColl: null };
224
+ parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false, value: {obj: selPointCollObj }});
225
+ prevObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true) as Point[];
226
+ }
227
+ parent.afterCropActions.push(degree === 90 ? 'rotateRight' : 'rotateLeft');
228
+ let splitWords: string[] = []; let activeObjShape: string;
229
+ if (parent.activeObj.activePoint && parent.activeObj.shape) {
230
+ if (parent.activeObj.shape !== undefined) {splitWords = parent.activeObj.shape.split('-'); }
231
+ if (parent.currObjType.isCustomCrop || splitWords[0] === 'crop') {
232
+ activeObjShape = parent.currObjType.isCustomCrop ? 'custom' : splitWords[1];
233
+ parent.notify('shape', { prop: 'updImgRatioForActObj', onPropertyChange: false});
234
+ parent.objColl.push(parent.activeObj);
235
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
236
+ }
237
+ }
238
+ parent.notify('shape', { prop: 'redrawActObj', onPropertyChange: false,
239
+ value: {x: null, y: null, isMouseDown: true}});
240
+ this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
241
+ this.drawRotatedImage(degree);
242
+ parent.notify('draw', { prop: 'setImageEdited', onPropertyChange: false });
243
+ parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.lowerContext}});
244
+ parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.upperContext}});
245
+ if (parent.isCircleCrop) {
246
+ parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
247
+ value: {context: this.lowerContext, isSave: null, isFlip: null}});
248
+ }
249
+ if (activeObjShape) {
250
+ this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
251
+ parent.activeObj = extend({}, parent.objColl[parent.objColl.length - 1], {}, true) as SelectionPoint;
252
+ parent.objColl.pop();
253
+ parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate', obj: parent.activeObj}});
254
+ }
255
+ parent.isUndoRedo = false; const obj: Object = {collection: parent.rotateFlipColl};
256
+ parent.notify('shape', { prop: 'alignRotateFlipColl', onPropertyChange: false,
257
+ value: {collection: parent.rotateFlipColl, isRotateFlipCollection: true, obj: obj }});
258
+ parent.rotateFlipColl = obj['collection'];
259
+ if (parent.cropObj.activeObj.shape && !this.isPreventSelect) {
260
+ parent.notify('draw', { prop: 'setIsCropSelect', value: {bool: true }});
261
+ this.isPreventSelect = true;
262
+ parent.notify('draw', { prop: 'select', onPropertyChange: false,
263
+ value: {type: 'custom', startX: null, startY: null, width: null, height: null }});
264
+ this.isPreventSelect = false;
265
+ parent.setProperties({zoomSettings: { zoomFactor: 1 }}, true);
266
+ this.prevZoomValue = parent.zoomSettings.zoomFactor;
267
+ }
268
+ } else {
269
+ parent.notify('draw', { prop: 'setCurrentObj', onPropertyChange: false, value: {obj: parent.prevEventObjPoint}});
270
+ parent.activeObj = parent.prevEventSelectionPoint;
271
+ parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate', obj: parent.activeObj}});
272
+ }
273
+ }
274
+
275
+ private drawRotatedImage(degree: number): void {
276
+ const parent: ImageEditor = this.parent;
277
+ if (degree === 0) {parent.transform.degree = 0; }
278
+ else {parent.transform.degree += degree; }
279
+ if (Math.abs(parent.transform.degree) === 360) {parent.transform.degree = 0; }
280
+ parent.notify('draw', { prop: 'setDestPoints', onPropertyChange: false});
281
+ const tempObjColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
282
+ const tempActiveObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
283
+ parent.objColl = [];
284
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
285
+ if (!this.isReverseRotate) {
286
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
287
+ value: {type: 'initial', isPreventDestination: null, isRotatePan: null} });
288
+ }
289
+ this.rotateDegree(degree);
290
+ if (!this.isReverseRotate) {
291
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
292
+ value: {type: 'reverse', isPreventDestination: null, isRotatePan: null} });
293
+ parent.rotateFlipColl.push(degree as number);
294
+ }
295
+ parent.objColl = extend([], tempObjColl, [], true) as SelectionPoint[];
296
+ parent.activeObj = extend({}, tempActiveObj, {}, true) as SelectionPoint;
297
+ if (parent.isCircleCrop) {
298
+ parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
299
+ value: {context: this.lowerContext, isSave: null, isFlip: null}});
300
+ }
301
+ parent.notify('shape', { prop: 'redrawObj', onPropertyChange: false, value: {degree: degree}});
302
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
303
+ if (degree > 0) {parent.notify('freehand-draw', { prop: 'rotateFhdColl', onPropertyChange: false}); }
304
+ else {
305
+ for (let i: number = 0; i < 3; i++) {
306
+ parent.notify('freehand-draw', { prop: 'rotateFhdColl', onPropertyChange: false});
307
+ }
308
+ }
309
+ parent.notify('freehand-draw', { prop: 'freehandRedraw', onPropertyChange: false,
310
+ value: {context: this.lowerContext, points: null} });
311
+ this.updateCurrSelectionPoint(degree);
312
+ }
313
+
314
+ private rotateDegree(degree: number): void {
315
+ const parent: ImageEditor = this.parent;
316
+ this.lowerContext.save();
317
+ this.lowerContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
318
+ this.lowerContext.translate(parent.lowerCanvas.width / 2, parent.lowerCanvas.height / 2);
319
+ this.lowerContext.rotate(Math.PI / 180 * degree);
320
+ this.lowerContext.translate(-parent.lowerCanvas.width / 2, -parent.lowerCanvas.height / 2);
321
+ const temp: string = this.lowerContext.filter;
322
+ parent.notify('draw', { prop: 'drawImage', onPropertyChange: false});
323
+ this.lowerContext.filter = temp;
324
+ this.lowerContext.translate(parent.lowerCanvas.width / 2, parent.lowerCanvas.height / 2);
325
+ this.lowerContext.rotate(Math.PI / 180 * -degree);
326
+ this.lowerContext.translate(-parent.lowerCanvas.width / 2, -parent.lowerCanvas.height / 2);
327
+ this.lowerContext.restore();
328
+ }
329
+
330
+ private updateCurrSelectionPoint(degree: number | string): void {
331
+ const parent: ImageEditor = this.parent;
332
+ if (parent.currSelectionPoint && this.currDestPoint) {
333
+ const activeObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
334
+ const objColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
335
+ const srcPoints: ActivePoint = {startX: parent.img.srcLeft, startY: parent.img.srcTop, width: parent.img.srcWidth,
336
+ height: parent.img.srcHeight};
337
+ const destPoints: ActivePoint = {startX: parent.img.destLeft, startY: parent.img.destTop, width: parent.img.destWidth,
338
+ height: parent.img.destHeight};
339
+ parent.objColl = [];
340
+ parent.objColl.push(extend({}, parent.currSelectionPoint, {}, true) as SelectionPoint);
341
+ parent.img = {srcLeft: 0, srcTop: 0, srcWidth: parent.baseImgCanvas.width, srcHeight: parent.baseImgCanvas.height,
342
+ destLeft: this.currDestPoint.startX, destTop: this.currDestPoint.startY, destWidth: this.currDestPoint.width,
343
+ destHeight: this.currDestPoint.height};
344
+ if (typeof(degree) === 'number') {
345
+ parent.notify('draw', { prop: 'setDestPoints', onPropertyChange: false});
346
+ parent.notify('draw', { prop: 'setClientTransDim', onPropertyChange: false,
347
+ value: {isPreventDimension: null}});
348
+ }
349
+ parent.notify('shape', { prop: 'redrawObj', onPropertyChange: false, value: {degree: degree}});
350
+ parent.currSelectionPoint = extend({}, parent.objColl[0], {}, true) as SelectionPoint;
351
+ this.currDestPoint = {startX: parent.img.destLeft, startY: parent.img.destTop, width: parent.img.destWidth,
352
+ height: parent.img.destHeight};
353
+ parent.objColl = objColl; parent.activeObj = activeObj;
354
+ parent.img = {srcLeft: srcPoints.startX, srcTop: srcPoints.startY, srcWidth: srcPoints.width, srcHeight: srcPoints.height,
355
+ destLeft: destPoints.startX, destTop: destPoints.startY, destWidth: destPoints.width, destHeight: destPoints.height};
356
+ }
357
+ }
358
+
359
+ private flipImage(direction: Direction): void {
360
+ const parent: ImageEditor = this.parent;
361
+ const transitionArgs: FlipEventArgs = {direction: direction, cancel: false,
362
+ previousDirection: parent.toPascalCase(parent.transform.currFlipState || direction )};
363
+ if (!this.isPreventSelect) {
364
+ parent.trigger('flipping', transitionArgs);
365
+ parent.editCompleteArgs = transitionArgs;
366
+ }
367
+ this.flipEvent(transitionArgs, direction);
368
+ }
369
+
370
+ private flipEvent(transitionArgs: FlipEventArgs, direction: Direction): void {
371
+ const parent: ImageEditor = this.parent;
372
+ if (transitionArgs.cancel) {
373
+ parent.notify('draw', { prop: 'setCurrentObj', onPropertyChange: false, value: {obj: parent.prevEventObjPoint}});
374
+ parent.activeObj = parent.prevEventSelectionPoint;
375
+ parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate', obj: parent.activeObj}});
376
+ return;
377
+ }
378
+ let prevObj: CurrentObject;
379
+ if (isNullOrUndefined(this.transCurrObj)) {
380
+ const object: Object = {currObj: {} as CurrentObject };
381
+ parent.notify('filter', { prop: 'getCurrentObj', onPropertyChange: false, value: {object: object }});
382
+ prevObj = object['currObj'];
383
+ prevObj.objColl = extend([], parent.objColl, null, true) as SelectionPoint[];
384
+ prevObj.pointColl = extend({}, parent.pointColl, null, true) as Point[];
385
+ prevObj.afterCropActions = extend([], parent.afterCropActions, [], true) as string[];
386
+ const selPointCollObj: Object = {selPointColl: null };
387
+ parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
388
+ value: {obj: selPointCollObj }});
389
+ prevObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true) as Point[];
390
+ }
391
+ parent.afterCropActions.push(direction.toLowerCase() === 'horizontal' ? 'horizontalflip' : 'verticalflip');
392
+ let splitWords: string[] = []; let activeObjShape: string;
393
+ if (parent.activeObj.activePoint) {
394
+ if (parent.activeObj.shape !== undefined) {splitWords = parent.activeObj.shape.split('-'); }
395
+ if (parent.currObjType.isCustomCrop || splitWords[0] === 'crop') {
396
+ activeObjShape = parent.currObjType.isCustomCrop ? 'custom' : splitWords[1];
397
+ parent.notify('shape', { prop: 'updImgRatioForActObj', onPropertyChange: false});
398
+ parent.objColl.push(parent.activeObj);
399
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
400
+ }
401
+ }
402
+ parent.notify('shape', { prop: 'redrawActObj', onPropertyChange: false,
403
+ value: {x: null, y: null, isMouseDown: true}});
404
+ parent.clearContext(this.lowerContext); parent.clearContext(this.upperContext);
405
+ const tempObjColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
406
+ const tempActiveObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
407
+ parent.objColl = [];
408
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
409
+ if (!this.isReverseFlip) {
410
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
411
+ value: {type: 'initial', isPreventDestination: null, isRotatePan: null} });
412
+ }
413
+ const lowercaseDirection: string = direction.toLowerCase();
414
+ this.updateFlipState(lowercaseDirection);
415
+ const flipState: string = parent.transform.currFlipState.toLowerCase();
416
+ parent.transform.currFlipState = (lowercaseDirection === 'horizontal' && flipState === 'horizontal') ||
417
+ (lowercaseDirection === 'vertical' && flipState === 'vertical') ? '' : lowercaseDirection;
418
+ const selObj: Object = {isSelected: null };
419
+ parent.notify('draw', { prop: 'getRotatedFlipCropSelection', onPropertyChange: false, value: {bool: selObj }});
420
+ if (selObj['isSelected']) {
421
+ parent.img.destLeft += parent.panPoint.totalPannedInternalPoint.x;
422
+ parent.img.destTop += parent.panPoint.totalPannedInternalPoint.y;
423
+ }
424
+ const temp: string = this.lowerContext.filter;
425
+ parent.notify('draw', { prop: 'drawImage', onPropertyChange: false});
426
+ this.lowerContext.filter = temp;
427
+ parent.notify('draw', { prop: 'setImageEdited', onPropertyChange: false });
428
+ this.updateFlipState(direction.toLowerCase());
429
+ if (!this.isReverseFlip) {
430
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
431
+ value: {type: 'reverse', isPreventDestination: null, isRotatePan: null} });
432
+ this.updateFlipColl(direction.toLocaleLowerCase());
433
+ parent.rotateFlipColl.push(direction.toLowerCase());
434
+ }
435
+ if (parent.rotateFlipColl.length === 1) {
436
+ const panObj: Object = {panRegion: '' };
437
+ parent.notify('crop', { prop: 'getCurrFlipState', onPropertyChange: false,
438
+ value: {panObj: panObj }});
439
+ if (panObj['panRegion'] === '') {
440
+ parent.notify('draw', { prop: 'setClientTransDim', onPropertyChange: false,
441
+ value: {isPreventDimension: null}});
442
+ } else {
443
+ this.setDestPointsForFlipState();
444
+ }
445
+ }
446
+ if (parent.isCircleCrop) {
447
+ parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
448
+ value: {context: this.lowerContext, isSave: null, isFlip: null}});
449
+ }
450
+ parent.objColl = extend([], tempObjColl, [], true) as SelectionPoint[];
451
+ parent.activeObj = extend({}, tempActiveObj, {}, true) as SelectionPoint;
452
+ for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
453
+ const flipObjColl: string[] = parent.objColl[i as number].flipObjColl;
454
+ if (flipObjColl.length === 0) {
455
+ flipObjColl.push(direction);
456
+ } else if (flipObjColl[flipObjColl.length - 1] === direction) {
457
+ flipObjColl.pop();
458
+ } else {
459
+ flipObjColl.push(direction);
460
+ }
461
+ }
462
+ parent.notify('shape', { prop: 'redrawObj', onPropertyChange: false, value: {degree: direction.toLowerCase()}});
463
+ const tempFilter: string = this.lowerContext.filter;
464
+ this.lowerContext.filter = 'brightness(' + 1 + ') ' + 'contrast(' + 100 + '%) ' + 'hue-rotate(' + 0 + 'deg) ' +
465
+ 'saturate(' + 100 + '%) ' + 'opacity(' + 1 + ') ' + 'blur(' + 0 + 'px) ' + 'sepia(0%) ' + 'grayscale(0%) ' + 'invert(0%)';
466
+ parent.notify('shape', { prop: 'iterateObjColl', onPropertyChange: false});
467
+ const dir: string = direction.toLowerCase();
468
+ if (dir === 'horizontal' || dir === 'vertical') {
469
+ parent.notify('freehand-draw', { prop: 'flipFHDColl', onPropertyChange: false,
470
+ value: {value: dir}});
471
+ parent.notify('freehand-draw', { prop: 'freehandRedraw', onPropertyChange: false,
472
+ value: {context: this.lowerContext, points: null} });
473
+ } else {
474
+ parent.notify('freehand-draw', { prop: 'freehandRedraw', onPropertyChange: false,
475
+ value: {context: this.lowerContext, points: null} });
476
+ }
477
+ this.lowerContext.filter = tempFilter;
478
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
479
+ this.updateCurrSelectionPoint(dir);
480
+ parent.isUndoRedo = false;
481
+ parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.lowerContext}});
482
+ parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.upperContext}});
483
+ if (parent.isCircleCrop) {
484
+ parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
485
+ value: {context: this.lowerContext, isSave: null, isFlip: null}});
486
+ }
487
+ if (activeObjShape) {
488
+ this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
489
+ parent.activeObj = extend({}, parent.objColl[parent.objColl.length - 1], {}, true) as SelectionPoint;
490
+ parent.objColl.pop();
491
+ parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate', obj: parent.activeObj}});
492
+ }
493
+ const obj: Object = {collection: parent.rotateFlipColl};
494
+ parent.notify('shape', { prop: 'alignRotateFlipColl', onPropertyChange: false,
495
+ value: {collection: parent.rotateFlipColl, isRotateFlipCollection: true, obj: obj }});
496
+ parent.rotateFlipColl = obj['collection'];
497
+ if (parent.cropObj.activeObj.shape && !this.isPreventSelect) {
498
+ parent.notify('draw', { prop: 'setIsCropSelect', value: {bool: true }});
499
+ this.isPreventSelect = true;
500
+ parent.notify('draw', { prop: 'select', onPropertyChange: false,
501
+ value: {type: 'custom', startX: null, startY: null, width: null, height: null }});
502
+ this.isPreventSelect = false;
503
+ parent.setProperties({zoomSettings: { zoomFactor: 1 }}, true);
504
+ this.prevZoomValue = parent.zoomSettings.zoomFactor;
505
+ }
506
+ }
507
+
508
+ private updateFlipState(direction: string): void {
509
+ const degree: number = this.parent.transform.degree;
510
+ if (direction === 'horizontal') {
511
+ if (degree % 90 === 0 && degree % 180 !== 0) {
512
+ this.verticalFlip();
513
+ } else {
514
+ this.horizontalFlip();
515
+ }
516
+ } else if (direction === 'vertical') {
517
+ if (degree % 90 === 0 && degree % 180 !== 0) {
518
+ this.horizontalFlip();
519
+ } else {
520
+ this.verticalFlip();
521
+ }
522
+ }
523
+ }
524
+
525
+ private horizontalFlip(): void {
526
+ this.lowerContext.translate(this.lowerContext.canvas.width, 0);
527
+ this.lowerContext.scale(-1, 1);
528
+ this.upperContext.translate(this.upperContext.canvas.width, 0);
529
+ this.upperContext.scale(-1, 1);
530
+ }
531
+
532
+ private verticalFlip(): void {
533
+ this.lowerContext.translate(0, this.lowerContext.canvas.height);
534
+ this.lowerContext.scale(1, -1);
535
+ this.upperContext.translate(0, this.upperContext.canvas.height);
536
+ this.upperContext.scale(1, -1);
537
+ }
538
+
539
+ private updateFlipColl(direction: string): void {
540
+ if (this.isPreventSelect) {
541
+ return;
542
+ }
543
+ if (this.flipColl.length === 0 || this.flipColl[this.flipColl.length - 1] !== direction) {
544
+ this.flipColl.push(direction);
545
+ } else {
546
+ this.flipColl.pop();
547
+ }
548
+ if (this.flipColl.length >= 4) {
549
+ const lastFourItems: string[] = this.flipColl.slice(-4);
550
+ if (
551
+ (lastFourItems[0] === 'horizontal' && lastFourItems[1] === 'vertical' &&
552
+ lastFourItems[2] === 'horizontal' && lastFourItems[3] === 'vertical') ||
553
+ (lastFourItems[0] === 'vertical' && lastFourItems[1] === 'horizontal' &&
554
+ lastFourItems[2] === 'vertical' && lastFourItems[3] === 'horizontal')
555
+ ) {
556
+ this.flipColl.splice(-4);
557
+ }
558
+ }
559
+ }
560
+
561
+ private setDestPointsForFlipState(): void {
562
+ const parent: ImageEditor = this.parent; const panObj: Object = {panRegion: '' };
563
+ const { destLeft, destTop, destWidth, destHeight } = parent.img;
564
+ const { clientWidth, clientHeight } = parent.lowerCanvas;
565
+ parent.notify('crop', { prop: 'getCurrFlipState', onPropertyChange: false,
566
+ value: {panObj: panObj }});
567
+ if (panObj['panRegion'] !== '') {
568
+ if (panObj['panRegion'] === 'horizontal') {
569
+ parent.img.destLeft = clientWidth - (destWidth + destLeft);
570
+ } else if (panObj['panRegion'] === 'vertical') {
571
+ parent.img.destTop = clientHeight - (destHeight + destTop);
572
+ } else {
573
+ parent.img.destLeft = clientWidth - (destWidth + destLeft);
574
+ parent.img.destTop = clientHeight - (destHeight + destTop);
575
+ }
576
+ }
577
+ }
578
+
579
+ private zoomAction(zoomFactor: number, zoomPoint?: Point, isResize?: boolean, isPreventApply?: boolean): void {
580
+ const parent: ImageEditor = this.parent;
581
+ if (!parent.disabled && parent.isImageLoaded) {
582
+ if (isNullOrUndefined(isResize) && (parent.zoomSettings.zoomFactor >= parent.zoomSettings.maxZoomFactor && zoomFactor > 0 ||
583
+ (parent.zoomSettings.zoomFactor > parent.zoomSettings.minZoomFactor && zoomFactor < 0 && this.disableZoomOutBtn(true)) ||
584
+ (parent.zoomSettings.zoomFactor <= parent.zoomSettings.minZoomFactor && zoomFactor < 0))) {
585
+ parent.notify('toolbar', { prop: 'zoom-up-handler', onPropertyChange: false});
586
+ return;
587
+ }
588
+ parent.notify('draw', { prop: 'setImageEdited', onPropertyChange: false });
589
+ const tempZoomFactor: number = zoomFactor;
590
+ zoomFactor = tempZoomFactor > 0 ? 0.1 : -0.1;
591
+ for (let i: number = 0; i < Math.round(Math.abs(tempZoomFactor / 0.1)); i++) {
592
+ if (this.prevZoomValue === 1) {
593
+ this.prevZoomValue += zoomFactor > 0 ? zoomFactor * 10 : (zoomFactor * 10) / 10;
594
+ } else if (this.prevZoomValue > 1) {
595
+ this.prevZoomValue += (zoomFactor * 10);
596
+ } else if (this.prevZoomValue < 1) {
597
+ this.prevZoomValue += (zoomFactor * 10) / 10;
598
+ const powerOften: number = Math.pow(10, 1);
599
+ this.prevZoomValue = (Math.round(this.prevZoomValue * powerOften ) / powerOften);
600
+ }
601
+ }
602
+ zoomFactor = tempZoomFactor;
603
+ parent.setProperties({zoomSettings: { zoomFactor: this.prevZoomValue}}, true);
604
+ let splitWords: string[]; this.tempActiveObj = null; this.isShape = false;
605
+ if (parent.activeObj.shape !== undefined) {
606
+ if (parent.activeObj.shape === 'shape') {
607
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
608
+ }
609
+ else {splitWords = parent.activeObj.shape.split('-'); }
610
+ }
611
+ if (splitWords !== undefined && splitWords[0] === 'crop') {
612
+ this.tempActiveObj = extend({}, parent.activeObj, {}, true) as SelectionPoint;
613
+ parent.isCropTab = true;
614
+ } else if (parent.activeObj.shape && splitWords[0] !== 'crop' &&
615
+ (parent.activeObj.activePoint.width !== 0 || parent.activeObj.activePoint.height !== 0) ||
616
+ (parent.activeObj.shape === 'path' && parent.activeObj.pointColl.length > 0)) {
617
+ this.isShape = true;
618
+ }
619
+ const obj: Object = {zoomType: null };
620
+ parent.notify('selection', { prop: 'getZoomType', onPropertyChange: false, value: {obj: obj }});
621
+ if (isNullOrUndefined(zoomPoint)) {
622
+ if (parent.isCropTab && this.tempActiveObj) {
623
+ zoomPoint = {x: parent.activeObj.activePoint.startX + (parent.activeObj.activePoint.width / 2),
624
+ y: parent.activeObj.activePoint.startY + (parent.activeObj.activePoint.height / 2) };
625
+ } else {
626
+ zoomPoint = {x: parent.lowerCanvas.clientWidth / 2, y: parent.lowerCanvas.clientHeight / 2 };
627
+ }
628
+ if (obj['zoomType'] === 'MouseWheel' || obj['zoomType'] === 'Pinch') {
629
+ zoomPoint = {x: parent.zoomSettings.zoomPoint.x, y: parent.zoomSettings.zoomPoint.y};
630
+ }
631
+ }
632
+ const previousZoomFactor: number = parent.zoomSettings.zoomFactor - (zoomFactor * 10);
633
+ const zoomEventArgs: ZoomEventArgs = {zoomPoint: zoomPoint, cancel: false, previousZoomFactor: previousZoomFactor,
634
+ currentZoomFactor: parent.zoomSettings.zoomFactor, zoomTrigger: obj['zoomType']};
635
+ if (!parent.isCropToolbar && parent.isZoomBtnClick) {
636
+ parent.trigger('zooming', zoomEventArgs);
637
+ parent.editCompleteArgs = zoomEventArgs;
638
+ }
639
+ this.zoomEvent(zoomEventArgs, zoomFactor, isPreventApply);
640
+ }
641
+ }
642
+
643
+ private zoomEvent(zoomEventArgs: ZoomEventArgs, zoomFact: number, isPreventApply?: boolean): void {
644
+ const parent: ImageEditor = this.parent;
645
+ let shapeId: string;
646
+ const { zoomFactor, minZoomFactor } = parent.zoomSettings;
647
+ if (zoomEventArgs.cancel) { parent.isZoomBtnClick = false; return; }
648
+ if (this.parent.activeObj.redactType !== 'blur' && this.parent.activeObj.redactType !== 'pixelate') {
649
+ parent.notify('toolbar', { prop: 'close-contextual-toolbar', onPropertyChange: false});
650
+ }
651
+ if (!parent.isCropTab && parent.activeObj.shape) {
652
+ shapeId = parent.activeObj.currIndex;
653
+ }
654
+ parent.notify('shape', { prop: 'redrawActObj', onPropertyChange: false,
655
+ value: {x: null, y: null, isMouseDown: true}});
656
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
657
+ this.upperContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
658
+ const object: Object = {canvasFilter: parent.canvasFilter };
659
+ this.lowerContext.filter = object['canvasFilter'];
660
+ parent.upperCanvas.style.cursor = parent.cursor = 'default';
661
+ let objColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
662
+ if (!parent.isCropTab) {
663
+ if (parent.transform.degree !== 0) {
664
+ parent.notify('shape', { prop: 'redrawActObj', onPropertyChange: false, value: {x: null, y: null, isMouseDown: null}});
665
+ parent.panPoint.currentPannedPoint = {x: 0, y: 0};
666
+ const temp: boolean = parent.allowDownScale;
667
+ parent.allowDownScale = false;
668
+ this.rotatePan(true, true);
669
+ parent.allowDownScale = temp;
670
+ } else if (parent.transform.currFlipState !== '') {
671
+ parent.panPoint.totalPannedPoint = {x: 0, y: 0};
672
+ }
673
+ if (parent.transform.straighten === 0 && !this.isPreventSelect) {
674
+ parent.notify('freehand-draw', { prop: 'updateFHDColl', onPropertyChange: false, value: {isPreventApply: isPreventApply }});
675
+ }
676
+ }
677
+ if (parent.transform.degree === 0) {
678
+ this.drawZoomImgToCanvas(zoomFact, this.tempActiveObj);
679
+ const panObj: Object = {panRegion: '' };
680
+ parent.notify('crop', { prop: 'getCurrFlipState', onPropertyChange: false, value: {panObj: panObj }});
681
+ if (panObj['panRegion'] !== '') {
682
+ parent.notify('crop', { prop: 'setTempFlipPanPoint', onPropertyChange: false, value: {point: parent.panPoint.totalPannedPoint, isAdd: true }});
683
+ objColl = extend([], parent.objColl, [], true) as SelectionPoint[];
684
+ parent.objColl = [];
685
+ const destLeft: number = parent.img.destLeft; const destTop: number = parent.img.destTop;
686
+ this.setDestPointsForFlipState();
687
+ this.rotatedFlip();
688
+ parent.img.destLeft = destLeft; parent.img.destTop = destTop;
689
+ parent.objColl = objColl;
690
+ parent.notify('shape', { prop: 'drawAnnotations', onPropertyChange: false,
691
+ value: {ctx: this.lowerContext, shape: 'zoom', pen: 'zoom', isPreventApply: isPreventApply }});
692
+ if (parent.transform.straighten === 0 && !this.isPreventSelect) {
693
+ parent.notify('freehand-draw', { prop: 'updateFHDColl', onPropertyChange: false, value: {isPreventApply: isPreventApply }});
694
+ }
695
+ }
696
+ if (zoomFactor <= minZoomFactor && !parent.isCropTab) {
697
+ parent.panPoint.totalPannedPoint = { x: 0, y: 0 };
698
+ }
699
+ } else {
700
+ if (parent.transform.straighten === 0 && !this.isPreventSelect) {
701
+ parent.notify('freehand-draw', { prop: 'updateFHDColl', onPropertyChange: false, value: {isPreventApply: isPreventApply }});
702
+ }
703
+ parent.panPoint.totalPannedClientPoint = { x: 0, y: 0 };
704
+ parent.panPoint.totalPannedInternalPoint = { x: 0, y: 0 };
705
+ this.rotateZoom(zoomFact);
706
+ const panObj: Object = {panRegion: '' };
707
+ parent.notify('crop', { prop: 'getCurrFlipState', onPropertyChange: false, value: {panObj: panObj }});
708
+ if (panObj['panRegion'] !== '') {
709
+ const temp: string = this.lowerContext.filter;
710
+ this.lowerContext.filter = 'none';
711
+ parent.notify('shape', { prop: 'drawAnnotations', onPropertyChange: false,
712
+ value: {ctx: this.lowerContext, shape: 'zoom', pen: 'zoom', isPreventApply: isPreventApply }});
713
+ this.lowerContext.filter = temp;
714
+ }
715
+ }
716
+ const powerOften: number = Math.pow(10, 1);
717
+ if (zoomFactor <= minZoomFactor ||
718
+ (Math.round(parent.transform.zoomFactor * powerOften ) / powerOften) === 2) {
719
+ clearInterval(this.zoomBtnHold); this.zoomBtnHold = 0;
720
+ }
721
+ const panObj: Object = {panRegion: '' };
722
+ parent.notify('crop', { prop: 'getCurrFlipState', onPropertyChange: false, value: {panObj: panObj }});
723
+ if (panObj['panRegion'] === '') {
724
+ const temp: string = this.lowerContext.filter;
725
+ this.lowerContext.filter = 'none';
726
+ parent.notify('shape', { prop: 'drawAnnotations', onPropertyChange: false,
727
+ value: {ctx: this.lowerContext, shape: 'zoom', pen: 'zoom', isPreventApply: isPreventApply }});
728
+ this.lowerContext.filter = temp;
729
+ }
730
+ if ((parent.currSelectionPoint && parent.currSelectionPoint.shape === 'crop-circle') || parent.isCircleCrop) {
731
+ parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
732
+ value: {context: this.lowerContext, isSave: null, isFlip: null}});
733
+ }
734
+ parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.lowerContext}});
735
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
736
+ if (this.tempActiveObj) {
737
+ parent.activeObj = extend({}, this.tempActiveObj, {}, true) as SelectionPoint;
738
+ parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate', obj: parent.activeObj}});
739
+ if (zoomFactor <= minZoomFactor) {parent.currSelectionPoint = null; }
740
+ }
741
+ parent.isUndoRedo = false;
742
+ let zoomOut: HTMLElement;
743
+ zoomOut = document.querySelector('#' + parent.element.id + '_zoomOut');
744
+ if (zoomOut && zoomFactor <= minZoomFactor) {
745
+ zoomOut.classList.add('e-disabled');
746
+ zoomOut.parentElement.classList.add('e-overlay');
747
+ } else if (zoomOut) {
748
+ zoomOut.classList.remove('e-disabled');
749
+ zoomOut.parentElement.classList.remove('e-overlay');
750
+ }
751
+ const drawingShape: string = parent.drawingShape;
752
+ this.autoEnablePan();
753
+ parent.drawingShape = drawingShape;
754
+ if (this.tempActiveObj) {
755
+ parent.activeObj = extend({}, this.tempActiveObj, {}, true) as SelectionPoint;
756
+ }
757
+ if (parent.activeObj.shape === 'crop-custom') {parent.currObjType.isCustomCrop = true; }
758
+ if (this.isShape) {
759
+ if (shapeId) {
760
+ for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
761
+ if (parent.objColl[i as number].currIndex === shapeId) {
762
+ parent.activeObj = extend({}, parent.objColl[i as number], {}, true) as SelectionPoint;
763
+ parent.objColl.splice(i, 1);
764
+ break;
765
+ }
766
+ }
767
+ } else {
768
+ parent.activeObj = extend({}, parent.objColl[parent.objColl.length - 1], {}, true) as SelectionPoint;
769
+ parent.objColl.pop();
770
+ }
771
+ parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate', obj: parent.activeObj, isCropRatio: null,
772
+ points: null, isPreventDrag: true, saveContext: null, isPreventSelection: null} });
773
+ parent.notify('toolbar', { prop: 'update-toolbar-items', onPropertyChange: false});
774
+ parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: {isPenEdit: null} });
775
+ }
776
+ parent.notify('toolbar', { prop: 'enable-disable-btns', onPropertyChange: false});
777
+ parent.notify('selection', { prop: 'setZoomType', onPropertyChange: false, value: {zoomType: 'Toolbar' }});
778
+ // eslint-disable-next-line max-len
779
+ zoomEventArgs = { zoomPoint: zoomEventArgs.zoomPoint, previousZoomFactor: zoomEventArgs.previousZoomFactor, currentZoomFactor: zoomEventArgs.currentZoomFactor, zoomTrigger: zoomEventArgs.zoomTrigger};
780
+ if (!parent.isCropToolbar && parent.isZoomBtnClick) {
781
+ parent.isZoomBtnClick = false;
782
+ }
783
+ if (parent.drawingShape) {
784
+ const activeObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
785
+ parent.enableShapeDrawing(parent.toPascalCase(parent.drawingShape) as ShapeType, true);
786
+ parent.activeObj = activeObj;
787
+ if (activeObj.activePoint.width > 0 || activeObj.activePoint.height > 0 ||
788
+ (activeObj.pointColl && activeObj.pointColl.length > 0)) {
789
+ if (activeObj.shape === 'redact') {
790
+ parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: { isPenEdit: null } });
791
+ }
792
+ const zOrderElem: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_zOrderBtn');
793
+ const dupElem: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_duplicate');
794
+ const removeElem: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_remove');
795
+ const editTextElem: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_editText');
796
+ if (zOrderElem) {zOrderElem.classList.remove('e-overlay'); }
797
+ if (dupElem) {dupElem.classList.remove('e-overlay'); }
798
+ if (removeElem) {removeElem.classList.remove('e-overlay'); }
799
+ if (editTextElem) {editTextElem.classList.remove('e-overlay'); }
800
+ }
801
+ } else if (parent.activeObj.shape && parent.activeObj.shape === 'redact') {
802
+ parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: { type: 'redact',
803
+ isApplyBtn: false, isCropping: false } });
804
+ parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: { isPenEdit: null } });
805
+ }
806
+ }
807
+
808
+ private disableZoomOutBtn(isZoomOut?: boolean): boolean {
809
+ const parent: ImageEditor = this.parent; const { zoomFactor, minZoomFactor } = parent.zoomSettings;
810
+ let isDisabled: boolean = false;
811
+ let zoomOut: HTMLElement;
812
+ if (!isNullOrUndefined(isZoomOut)) {
813
+ parent.transform.zoomFactor -= 0.1;
814
+ }
815
+ zoomOut = parent.element.querySelector('#' + parent.element.id + '_zoomOut');
816
+ const destPoints: Object = {destLeft: parent.img.destLeft, destTop: parent.img.destTop,
817
+ destWidth: parent.img.destWidth, destHeight: parent.img.destHeight };
818
+ if (parent.activeObj.shape) {
819
+ const maxDimension: Dimension = this.setZoomDimension(-0.1, parent.activeObj);
820
+ const actPoint: ActivePoint = parent.activeObj.activePoint;
821
+ if (parent.transform.straighten === 0) {
822
+ if (parent.img.destLeft > actPoint.startX || parent.img.destTop >
823
+ actPoint.startY || parent.img.destLeft + parent.img.destWidth <
824
+ actPoint.endX || parent.img.destTop + parent.img.destHeight < actPoint.endY
825
+ || zoomFactor === minZoomFactor) {
826
+ isDisabled = true;
827
+ } else {
828
+ isDisabled = false;
829
+ }
830
+ } else {
831
+ parent.img.destWidth = maxDimension.width; parent.img.destHeight = maxDimension.height;
832
+ const obj: Object = {isIntersect: null };
833
+ parent.notify('draw', { prop: 'updateImgCanvasPoints', onPropertyChange: false });
834
+ parent.notify('draw', { prop: 'isLinesIntersect', onPropertyChange: false, value: {obj: obj }});
835
+ if (obj['isIntersect'] ||
836
+ zoomFactor === minZoomFactor) {
837
+ isDisabled = true;
838
+ } else {
839
+ isDisabled = false;
840
+ }
841
+ }
842
+ if (zoomOut) {
843
+ if (isDisabled) {
844
+ zoomOut.classList.add('e-disabled');
845
+ zoomOut.parentElement.classList.add('e-overlay');
846
+ } else {
847
+ zoomOut.classList.remove('e-disabled');
848
+ zoomOut.parentElement.classList.remove('e-overlay');
849
+ }
850
+ }
851
+ } else {
852
+ this.setZoomDimension(-0.1, null);
853
+ }
854
+ if (!isNullOrUndefined(isZoomOut)) {
855
+ parent.transform.zoomFactor += 0.1;
856
+ }
857
+ parent.img.destLeft = destPoints['destLeft']; parent.img.destTop = destPoints['destTop'];
858
+ parent.img.destWidth = destPoints['destWidth']; parent.img.destHeight = destPoints['destHeight'];
859
+ return isDisabled;
860
+ }
861
+
862
+ private drawZoomImgToCanvas(value: number, selectionObj?: SelectionPoint): void {
863
+ const parent: ImageEditor = this.parent;
864
+ const powerOften: number = Math.pow(10, 1);
865
+ const zmFactor: number = Math.round(parent.transform.zoomFactor * powerOften ) / powerOften;
866
+ if ((zmFactor === 0.1 && value === -0.1) || zmFactor === 0 && value === -0.025) {
867
+ parent.transform.zoomFactor = 0;
868
+ } else {parent.transform.zoomFactor += value; }
869
+ parent.transform[parent.isCropTab ? 'cropZoomFactor' : 'defaultZoomFactor'] = parent.transform.zoomFactor;
870
+ let maxDimension: Dimension = {width: 0, height: 0};
871
+ if (parent.isCropTab) {
872
+ maxDimension = this.cropZoom(value, selectionObj);
873
+ } else {
874
+ maxDimension = this.calcMaxDimension(parent.img.srcWidth, parent.img.srcHeight);
875
+ maxDimension.width += (maxDimension.width * parent.transform.zoomFactor);
876
+ maxDimension.height += (maxDimension.height * parent.transform.zoomFactor);
877
+ parent.img.destLeft = (parent.lowerCanvas.clientWidth - maxDimension.width) / 2;
878
+ parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height) / 2;
879
+ }
880
+ parent.notify('draw', {prop: 'draw-image-to-canvas', value: {dimension: maxDimension } });
881
+ maxDimension.width = this.cropDimension.width; maxDimension.height = this.cropDimension.height;
882
+ maxDimension.width += (maxDimension.width * parent.transform.zoomFactor);
883
+ maxDimension.height += (maxDimension.height * parent.transform.zoomFactor);
884
+ parent.notify('draw', {prop: 'setZoomCropWidth', value: {width: maxDimension.width, height: maxDimension.height }});
885
+ }
886
+
887
+ private rotatedFlip(): void {
888
+ const parent: ImageEditor = this.parent;
889
+ this.isReverseFlip = true;
890
+ let tempCurrFlipState: string = parent.transform.currFlipState;
891
+ const tempFlipColl: string[] = this.flipColl;
892
+ const tempObjColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
893
+ const tempActiveObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
894
+ this.flipColl = []; parent.objColl = [];
895
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
896
+ parent.notify('draw', { prop: 'currTransState', onPropertyChange: false,
897
+ value: {type: 'initial', isPreventDestination: null, context: null, isPreventCircleCrop: null} });
898
+ const temp: string = this.lowerContext.filter;
899
+ parent.notify('draw', { prop: 'drawImage', onPropertyChange: false});
900
+ this.lowerContext.filter = temp;
901
+ parent.notify('draw', { prop: 'currTransState', onPropertyChange: false,
902
+ value: {type: 'reverse', isPreventDestination: true, context: null, isPreventCircleCrop: null} });
903
+ if (tempCurrFlipState === '' && parent.transform.currFlipState !== '') {
904
+ tempCurrFlipState = parent.transform.currFlipState;
905
+ }
906
+ parent.transform.currFlipState = tempCurrFlipState;
907
+ this.flipColl = tempFlipColl;
908
+ parent.objColl = extend([], tempObjColl, [], true) as SelectionPoint[];
909
+ this.lowerContext.filter = 'none';
910
+ parent.notify('shape', { prop: 'iterateObjColl', onPropertyChange: false});
911
+ this.lowerContext.filter = temp;
912
+ if (tempActiveObj.activePoint.width !== 0) {
913
+ parent.activeObj = extend({}, tempActiveObj, {}, true) as SelectionPoint;
914
+ }
915
+ this.isReverseFlip = false;
916
+ }
917
+
918
+ private rotateZoom(value: number): void {
919
+ const parent: ImageEditor = this.parent;
920
+ const powerOften: number = Math.pow(10, 1);
921
+ const zmFactor: number = Math.round(parent.transform.zoomFactor * powerOften ) / powerOften;
922
+ if ((zmFactor === 0.1 && value === -0.1) || zmFactor === 0 && value === -0.025) {
923
+ parent.transform.zoomFactor = 0;
924
+ } else {parent.transform.zoomFactor += value; }
925
+ if (parent.isCropTab) {
926
+ parent.transform.cropZoomFactor = parent.transform.zoomFactor;
927
+ } else {
928
+ parent.transform.defaultZoomFactor = parent.transform.zoomFactor;
929
+ }
930
+ const tempObjColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
931
+ const tempActiveObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
932
+ parent.objColl = [];
933
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
934
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
935
+ value: {type: 'initial', isPreventDestination: null, isRotatePan: null} });
936
+ parent.notify('draw', { prop: 'setRotateZoom', onPropertyChange: false, value: {isRotateZoom: true }});
937
+ parent.notify('draw', { prop: 'setDestPoints', onPropertyChange: false});
938
+ const temp: string = this.lowerContext.filter;
939
+ parent.notify('draw', { prop: 'drawImage', onPropertyChange: false});
940
+ this.lowerContext.filter = temp;
941
+ parent.notify('draw', { prop: 'setRotateZoom', onPropertyChange: false, value: {isRotateZoom: false }});
942
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
943
+ value: {type: 'reverse', isPreventDestination: null, isRotatePan: null} });
944
+ parent.objColl = tempObjColl;
945
+ parent.activeObj = tempActiveObj;
946
+ const maxDimension: Dimension = {width: this.cropDimension.width, height: this.cropDimension.height };
947
+ maxDimension.width += (maxDimension.width * parent.transform.zoomFactor);
948
+ maxDimension.height += (maxDimension.height * parent.transform.zoomFactor);
949
+ parent.notify('draw', {prop: 'setZoomCropWidth', value: {width: maxDimension.width, height: maxDimension.height }});
950
+ }
951
+
952
+ private autoEnablePan(): void {
953
+ const parent: ImageEditor = this.parent;
954
+ if (parent.transform.zoomFactor <= 0) {
955
+ parent.togglePan = false;
956
+ parent.notify('selection', {prop: 'setDragCanvas', value: {bool: false }});
957
+ parent.pan(false); this.disablePan = false;
958
+ } else {
959
+ parent.pan(!this.disablePan);
960
+ }
961
+ }
962
+
963
+ private cropZoom(value: number, selectionObj?: SelectionPoint): Dimension {
964
+ const parent: ImageEditor = this.parent;
965
+ let destLeft: number = parent.img.destLeft; let destTop: number = parent.img.destTop;
966
+ let maxDimension: Dimension = {width: 0, height: 0};
967
+ if (parent.transform.degree % 90 === 0 && parent.transform.degree % 180 !== 0) {
968
+ maxDimension = this.calcMaxDimension(parent.img.srcHeight, parent.img.srcWidth);
969
+ } else {
970
+ maxDimension = this.calcMaxDimension(parent.img.srcWidth, parent.img.srcHeight);
971
+ }
972
+ maxDimension.width += (maxDimension.width * parent.transform.zoomFactor);
973
+ maxDimension.height += (maxDimension.height * parent.transform.zoomFactor);
974
+ parent.img.destLeft = destLeft - ((maxDimension.width - parent.img.destWidth) / 2);
975
+ parent.img.destTop = destTop - ((maxDimension.height - parent.img.destHeight) / 2);
976
+ destLeft = parent.img.destLeft; destTop = parent.img.destTop;
977
+ if (selectionObj && parent.transform.straighten === 0) {
978
+ if (parent.img.destLeft > selectionObj.activePoint.startX) {
979
+ parent.img.destLeft = selectionObj.activePoint.startX;
980
+ if (parent.transform.degree === 0) {
981
+ parent.panPoint.totalPannedPoint.x -= (destLeft - parent.img.destLeft);
982
+ }
983
+ }
984
+ if (parent.img.destTop > selectionObj.activePoint.startY) {
985
+ parent.img.destTop = selectionObj.activePoint.startY;
986
+ if (parent.transform.degree === 0) {
987
+ parent.panPoint.totalPannedPoint.y -= (destTop - parent.img.destTop);
988
+ }
989
+ }
990
+ if (parent.img.destLeft + maxDimension.width < selectionObj.activePoint.endX) {
991
+ parent.img.destLeft = selectionObj.activePoint.endX - maxDimension.width;
992
+ if (parent.transform.degree === 0) {
993
+ parent.panPoint.totalPannedPoint.x -= (destLeft - parent.img.destLeft);
994
+ }
995
+ }
996
+ if (parent.img.destTop + maxDimension.height < selectionObj.activePoint.endY) {
997
+ parent.img.destTop = selectionObj.activePoint.endY - maxDimension.height;
998
+ if (parent.transform.degree === 0) {
999
+ parent.panPoint.totalPannedPoint.y -= (destTop - parent.img.destTop);
1000
+ }
1001
+ }
1002
+ }
1003
+ return maxDimension;
1004
+ }
1005
+
1006
+ private setZoomDimension(value: number, selectionObj: SelectionPoint): Dimension {
1007
+ const parent: ImageEditor = this.parent; const degree: number = parent.transform.degree;
1008
+ let maxDimension: Dimension = { width: 0, height: 0 };
1009
+ if (degree % 90 === 0 && degree % 180 !== 0) {
1010
+ maxDimension = this.calcMaxDimension(parent.img.srcHeight, parent.img.srcWidth);
1011
+ } else {
1012
+ maxDimension = this.calcMaxDimension(parent.img.srcWidth, parent.img.srcHeight);
1013
+ }
1014
+ maxDimension.width += (maxDimension.width * parent.transform.zoomFactor);
1015
+ maxDimension.height += (maxDimension.height * parent.transform.zoomFactor);
1016
+ parent.img.destLeft += ((parent.img.destWidth - maxDimension.width) / 2);
1017
+ parent.img.destTop += ((parent.img.destHeight - maxDimension.height) / 2);
1018
+ // While zoom out limit image to draw inside the selection range
1019
+ if (value < 0 && selectionObj) {
1020
+ const startX: number = selectionObj.activePoint.startX;
1021
+ const startY: number = selectionObj.activePoint.startY;
1022
+ const width: number = selectionObj.activePoint.width;
1023
+ const height: number = selectionObj.activePoint.height;
1024
+ const maxDestLeft: number = parent.img.destLeft + maxDimension.width;
1025
+ const maxDestTop: number = parent.img.destTop + maxDimension.height;
1026
+ if (parent.img.destLeft > startX) { parent.img.destLeft = startX; }
1027
+ if (parent.img.destTop > startY) { parent.img.destTop = startY; }
1028
+ if (maxDestLeft < startX + width) { parent.img.destLeft = startX + width - maxDimension.width; }
1029
+ if (maxDestTop < startY + height) { parent.img.destTop = startY + height - maxDimension.height; }
1030
+ } else if (value < 0 && isNullOrUndefined(selectionObj)) {
1031
+ if (parent.img.destLeft > 0) {parent.img.destLeft = 0; }
1032
+ if (parent.img.destTop > 0) {parent.img.destTop = 0; }
1033
+ if (parent.img.destLeft + maxDimension.width < parent.lowerCanvas.clientWidth) {
1034
+ parent.img.destLeft = parent.lowerCanvas.clientWidth - parent.img.destWidth;
1035
+ }
1036
+ if (parent.img.destTop + maxDimension.height < parent.lowerCanvas.clientHeight) {
1037
+ parent.img.destTop = parent.lowerCanvas.clientHeight - parent.img.destHeight;
1038
+ }
1039
+ }
1040
+ return maxDimension;
1041
+ }
1042
+
1043
+ private drawPannedImage(xDiff?: number, yDiff?: number): void {
1044
+ const parent: ImageEditor = this.parent;
1045
+ const obj: Object = {panDown: null };
1046
+ parent.notify('selection', { prop: 'getPanDown', onPropertyChange: false, value: {obj: obj }});
1047
+ const panEventArgs: PanEventArgs = {startPoint: obj['panDown'], endPoint: this.panMove, cancel: false};
1048
+ parent.trigger('panning', panEventArgs);
1049
+ if (panEventArgs.cancel) { return; }
1050
+ this.panEvent(xDiff, yDiff);
1051
+ }
1052
+
1053
+ private panEvent(xDiff?: number, yDiff?: number, isPanMethod?: boolean): void {
1054
+ const parent: ImageEditor = this.parent; let isObjCreated: boolean = false;
1055
+ if (parent.activeObj.shape && parent.activeObj.shape === 'shape') {
1056
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
1057
+ }
1058
+ if (isNullOrUndefined(parent.activeObj.shape)) {
1059
+ isObjCreated = true;
1060
+ const actPoint: ActivePoint = parent.activeObj.activePoint = {startX: parent.img.destLeft, startY: parent.img.destTop,
1061
+ endX: parent.img.destLeft + parent.img.destWidth, endY: parent.img.destTop + parent.img.destHeight};
1062
+ const startX: number = actPoint.startX;
1063
+ const startY: number = actPoint.startY;
1064
+ const endX: number = actPoint.endX;
1065
+ const endY: number = actPoint.endY;
1066
+ if (startX < 0) {actPoint.startX = 0; }
1067
+ if (startY < 0) {actPoint.startY = 0; }
1068
+ if (endX > parent.lowerCanvas.width) {actPoint.endX = parent.lowerCanvas.width; }
1069
+ if (endY > parent.lowerCanvas.height) {actPoint.endY = parent.lowerCanvas.height; }
1070
+ actPoint.width = actPoint.endX - actPoint.startX;
1071
+ actPoint.height = actPoint.endY - actPoint.startY;
1072
+ parent.activeObj.shape = 'crop-custom';
1073
+ const obj: Object = {strokeSettings: {} as StrokeSettings };
1074
+ parent.notify('shape', { prop: 'getStrokeSettings', onPropertyChange: false, value: {obj: obj }});
1075
+ parent.activeObj.strokeSettings = obj['strokeSettings'];
1076
+ parent.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: {actPoint: actPoint, obj: parent.activeObj,
1077
+ isMouseMove: null, x: null, y: null}});
1078
+ parent.isCropTab = true;
1079
+ }
1080
+ if (parent.transform.degree === 0) {
1081
+ let point: Point;
1082
+ if ((isNullOrUndefined(xDiff) && isNullOrUndefined(yDiff)) || isPanMethod) {
1083
+ if (isPanMethod) {
1084
+ point = this.updatePanPoints(xDiff, yDiff);
1085
+ } else {
1086
+ point = this.updatePanPoints();
1087
+ }
1088
+ } else {point = {x: xDiff, y: yDiff}; }
1089
+ parent.panPoint.totalPannedPoint.x += point.x; parent.panPoint.totalPannedPoint.y += point.y;
1090
+ const tempSelectionObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
1091
+ const temp: string = this.lowerContext.filter;
1092
+ this.drawPannImage(point, isObjCreated); this.lowerContext.filter = temp;
1093
+ this.tempPanMove = extend({}, this.panMove, {}, true) as Point;
1094
+ parent.activeObj = extend({}, tempSelectionObj, {}, true) as SelectionPoint;
1095
+ this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
1096
+ if (parent.activeObj.shape) {
1097
+ parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate', obj: parent.activeObj}});
1098
+ }
1099
+ } else {
1100
+ const tempFlipState: string = parent.transform.currFlipState; parent.isCropTab = true;
1101
+ if ((isNullOrUndefined(xDiff) && isNullOrUndefined(yDiff)) || isPanMethod) {
1102
+ if (isPanMethod) {
1103
+ parent.panPoint.currentPannedPoint = this.updatePanPoints(xDiff, yDiff);
1104
+ } else {
1105
+ parent.panPoint.currentPannedPoint = this.updatePanPoints();
1106
+ }
1107
+ } else {
1108
+ parent.panPoint.currentPannedPoint = {x: xDiff, y: yDiff};
1109
+ }
1110
+ parent.transform.currFlipState = tempFlipState; this.rotatePan(null, null, isObjCreated); parent.isCropTab = false;
1111
+ this.tempPanMove = extend({}, this.panMove, {}, true) as Point;
1112
+ }
1113
+ if (isObjCreated) {
1114
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false}); parent.isCropTab = false;
1115
+ this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
1116
+ }
1117
+ }
1118
+
1119
+ private drawPannImage(point: Point, isObjCreated?: boolean): void {
1120
+ const parent: ImageEditor = this.parent;
1121
+ const filter: string = this.lowerContext.filter;
1122
+ const destPoints: ActivePoint = {startX: parent.img.destLeft, startY: parent.img.destTop, width: parent.img.destWidth,
1123
+ height: parent.img.destHeight};
1124
+ this.lowerContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
1125
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
1126
+ value: {type: 'initial', isPreventDestination: null, isRotatePan: null} });
1127
+ parent.img.destLeft = destPoints.startX; parent.img.destTop = destPoints.startY;
1128
+ parent.img.destWidth = destPoints.width; parent.img.destHeight = destPoints.height;
1129
+ this.setDestPointsForFlipState();
1130
+ if (isObjCreated) {parent.isCropTab = false; }
1131
+ parent.notify('draw', { prop: 'drawImage', onPropertyChange: false});
1132
+ if (isObjCreated) {parent.isCropTab = true; }
1133
+ if ((parent.currSelectionPoint && parent.currSelectionPoint.shape === 'crop-circle') || parent.isCircleCrop) {
1134
+ parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
1135
+ value: {context: this.lowerContext, isSave: null, isFlip: true}});
1136
+ }
1137
+ this.lowerContext.filter = filter;
1138
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
1139
+ value: {type: 'reverse', isPreventDestination: null, isRotatePan: null} });
1140
+ parent.img.destLeft = destPoints.startX; parent.img.destTop = destPoints.startY;
1141
+ parent.img.destWidth = destPoints.width; parent.img.destHeight = destPoints.height;
1142
+ const temp: string = this.lowerContext.filter;
1143
+ this.lowerContext.filter = 'none';
1144
+ if (isObjCreated) {parent.isCropTab = false; }
1145
+ parent.notify('shape', { prop: 'drawAnnotations', onPropertyChange: false,
1146
+ value: {ctx: this.lowerContext, shape: 'pan', pen: 'pan', x: point.x,
1147
+ y: point.y, panRegion: '' }});
1148
+ if (isObjCreated) {parent.isCropTab = true; }
1149
+ this.lowerContext.filter = temp;
1150
+ parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.lowerContext}});
1151
+ if (parent.isCircleCrop) {
1152
+ parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
1153
+ value: {context: this.lowerContext, isSave: null, isFlip: true}});
1154
+ }
1155
+ }
1156
+
1157
+ private resetZoom(): void {
1158
+ const parent: ImageEditor = this.parent;
1159
+ if (parent.transform.defaultZoomFactor !== 0) {
1160
+ const isUndoRedo: boolean = parent.isUndoRedo;
1161
+ const object: Object = {currObj: {} as CurrentObject };
1162
+ parent.notify('filter', { prop: 'getCurrentObj', onPropertyChange: false, value: {object: object }});
1163
+ this.transCurrObj = object['currObj'];
1164
+ this.transCurrObj.objColl = extend([], parent.objColl, null, true) as SelectionPoint[];
1165
+ this.transCurrObj.pointColl = extend({}, parent.pointColl, null, true) as Point[];
1166
+ this.transCurrObj.afterCropActions = extend([], parent.afterCropActions, [], true) as string[];
1167
+ const selPointCollObj: Object = {selPointColl: null };
1168
+ parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
1169
+ value: {obj: selPointCollObj }});
1170
+ this.transCurrObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true) as Point[];
1171
+ parent.isUndoRedo = parent.isCropToolbar = true;
1172
+ const zmFactor: number = parent.transform.defaultZoomFactor;
1173
+ if (zmFactor > 0) {
1174
+ this.zoomAction(-zmFactor);
1175
+ } else {
1176
+ this.zoomAction(Math.abs(zmFactor));
1177
+ }
1178
+ parent.isCropToolbar = false; parent.isUndoRedo = isUndoRedo;
1179
+ }
1180
+ }
1181
+
1182
+ private performTransformation(text: string): void {
1183
+ const parent: ImageEditor = this.parent;
1184
+ this.resetZoom();
1185
+ this.updateTransform(text);
1186
+ for (let i: number = 0, len: number = parent.objColl.length; i < len; i++) {
1187
+ if (parent.objColl[i as number].flipObjColl.length > 0) {
1188
+ const flipObjColl: Object = {collection: parent.objColl[i as number].flipObjColl };
1189
+ parent.notify('shape', { prop: 'alignRotateFlipColl', onPropertyChange: false,
1190
+ value: {collection: flipObjColl['collection'], isRotateFlipCollection: null, obj: flipObjColl }});
1191
+ parent.objColl[i as number].flipObjColl = flipObjColl['collection'];
1192
+ if (parent.objColl[i as number].flipObjColl.length === 0) {
1193
+ parent.objColl[i as number].shapeFlip = '';
1194
+ }
1195
+ }
1196
+ }
1197
+ }
1198
+
1199
+ private updateTransform(text: string): void {
1200
+ switch (text.toLowerCase()) {
1201
+ case 'rotateleft':
1202
+ this.rotateImage(-90);
1203
+ break;
1204
+ case 'rotateright':
1205
+ this.rotateImage(90);
1206
+ break;
1207
+ case 'horizontalflip':
1208
+ this.flipImage(Direction.Horizontal);
1209
+ break;
1210
+ case 'verticalflip':
1211
+ this.flipImage(Direction.Vertical);
1212
+ break;
1213
+ }
1214
+ }
1215
+
1216
+ private rotatePan(isCropSelection?: boolean, isDefaultZoom?: boolean, isObjCreated?: boolean): void {
1217
+ const parent: ImageEditor = this.parent; this.isReverseRotate = true;
1218
+ const tempDegree: number = parent.transform.degree;
1219
+ let rotatePanActiveObj: SelectionPoint; const object: Object = {selPointColl: null };
1220
+ if (parent.activeObj.activePoint && parent.activeObj.shape) {
1221
+ rotatePanActiveObj = extend({}, parent.activeObj, {}, true) as SelectionPoint;
1222
+ }
1223
+ const tempObjColl: SelectionPoint[] = extend([], parent.objColl, [], true) as SelectionPoint[];
1224
+ const tempPointColl: Point[] = extend([], parent.pointColl, [], true) as Point[];
1225
+ parent.objColl = []; parent.pointColl = []; parent.freehandCounter = 0;
1226
+ parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false, value: {obj: object }});
1227
+ const cropSelPointColl: Point[] = object['selPointColl'];
1228
+ parent.notify('freehand-draw', { prop: 'setSelPointColl', onPropertyChange: false, value: {obj: {selPointColl: [] } }});
1229
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
1230
+ parent.notify('draw', { prop: 'setRotateZoom', onPropertyChange: false, value: {isRotateZoom: true }});
1231
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
1232
+ value: {type: 'initial', isPreventDestination: null, isRotatePan: null} });
1233
+ const initialDestLeft: number = parent.img.destLeft; const initialDestTop: number = parent.img.destTop;
1234
+ const intPan: Point = parent.panPoint.totalPannedInternalPoint;
1235
+ if (parent.isCropTab) {
1236
+ parent.img.destLeft += intPan.x;
1237
+ parent.img.destTop += intPan.y;
1238
+ }
1239
+ parent.notify('crop', { prop: 'updateRotatePan', onPropertyChange: false});
1240
+ if (parent.isCropTab) {
1241
+ parent.panPoint.totalPannedInternalPoint.x = parent.img.destLeft - initialDestLeft;
1242
+ parent.panPoint.totalPannedInternalPoint.y = parent.img.destTop - initialDestTop;
1243
+ }
1244
+ const temp: string = this.lowerContext.filter;
1245
+ if (isObjCreated) {parent.isCropTab = false; }
1246
+ parent.notify('draw', { prop: 'drawImage', onPropertyChange: false});
1247
+ if (isObjCreated) {parent.isCropTab = true; }
1248
+ parent.notify('draw', { prop: 'setRotateZoom', onPropertyChange: false, value: {isRotateZoom: false }});
1249
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
1250
+ value: {type: 'reverse', isPreventDestination: true, isRotatePan: true} });
1251
+ const destLeft: number = parent.img.destLeft; const destTop: number = parent.img.destTop;
1252
+ parent.img.destLeft += parent.panPoint.totalPannedClientPoint.x;
1253
+ parent.img.destTop += parent.panPoint.totalPannedClientPoint.y;
1254
+ parent.img.destLeft += parent.panPoint.currentPannedPoint.x;
1255
+ parent.img.destTop += parent.panPoint.currentPannedPoint.y;
1256
+ parent.panPoint.totalPannedClientPoint.x = parent.img.destLeft - destLeft;
1257
+ parent.panPoint.totalPannedClientPoint.y = parent.img.destTop - destTop;
1258
+ parent.objColl = tempObjColl; parent.pointColl = tempPointColl; parent.freehandCounter = parent.pointColl.length;
1259
+ parent.notify('freehand-draw', { prop: 'setSelPointColl', onPropertyChange: false,
1260
+ value: {obj: {selPointColl: cropSelPointColl } }});
1261
+ parent.transform.degree = tempDegree;
1262
+ this.lowerContext.filter = 'none';
1263
+ if (isCropSelection) {
1264
+ if (isDefaultZoom) {
1265
+ parent.panPoint.totalPannedClientPoint.x = -parent.panPoint.totalPannedClientPoint.x;
1266
+ parent.panPoint.totalPannedClientPoint.y = -parent.panPoint.totalPannedClientPoint.y;
1267
+ parent.panPoint.currentPannedPoint = extend({}, parent.panPoint.totalPannedClientPoint, {}, true) as Point;
1268
+ parent.panPoint.totalPannedClientPoint = { x: 0, y: 0 };
1269
+ parent.img.destLeft += parent.panPoint.currentPannedPoint.x;
1270
+ parent.img.destTop += parent.panPoint.currentPannedPoint.y;
1271
+ } else {
1272
+ parent.panPoint.currentPannedPoint = extend({}, parent.panPoint.totalPannedClientPoint, {}, true) as Point;
1273
+ }
1274
+ }
1275
+ if (isObjCreated) {parent.isCropTab = false; }
1276
+ parent.notify('shape', { prop: 'drawAnnotations', onPropertyChange: false,
1277
+ value: {ctx: this.lowerContext, shape: 'pan', pen: 'pan', x: parent.panPoint.currentPannedPoint.x,
1278
+ y: parent.panPoint.currentPannedPoint.y, panRegion: '' }});
1279
+ if (isObjCreated) {parent.isCropTab = true; }
1280
+ this.lowerContext.filter = temp;
1281
+ parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.lowerContext}});
1282
+ this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
1283
+ parent.activeObj = extend({}, rotatePanActiveObj, {}, true) as SelectionPoint;
1284
+ if (parent.activeObj.activePoint) {
1285
+ parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate', obj: parent.activeObj, isCropRatio: null,
1286
+ points: null, isPreventDrag: true, saveContext: null, isPreventSelection: null} });
1287
+ }
1288
+ this.isReverseRotate = false;
1289
+ }
1290
+
1291
+ private limitPan(): void {
1292
+ const parent: ImageEditor = this.parent;
1293
+ const { startX, startY, endX, endY } = parent.activeObj.activePoint;
1294
+ const img: ImageDimension = parent.img;
1295
+ if (parent.activeObj.activePoint) {
1296
+ if (img.destLeft > startX) {
1297
+ parent.img.destLeft = startX;
1298
+ }
1299
+ if (img.destTop > startY) {
1300
+ parent.img.destTop = startY;
1301
+ }
1302
+ if (img.destLeft + img.destWidth < endX) {
1303
+ parent.img.destLeft = endX - img.destWidth;
1304
+ }
1305
+ if (img.destTop + img.destHeight < endY) {
1306
+ parent.img.destTop = endY - img.destHeight;
1307
+ }
1308
+ }
1309
+ }
1310
+
1311
+ private pan(value: boolean, x?: number, y?: number): void {
1312
+ const parent: ImageEditor = this.parent;
1313
+ if (!parent.disabled && parent.isImageLoaded) {
1314
+ if (value) {
1315
+ parent.togglePan = true;
1316
+ parent.notify('shape', { prop: 'redrawActObj', onPropertyChange: false,
1317
+ value: {x: null, y: null, isMouseDown: null}});
1318
+ parent.notify('selection', {prop: 'setDragCanvas', value: {bool: true }});
1319
+ parent.lowerCanvas.style.cursor = parent.upperCanvas.style.cursor = parent.cursor = 'grab';
1320
+ parent.notify('selection', { prop: 'setPanDown', onPropertyChange: false, value: {panDown: null }});
1321
+ if (x || y) {
1322
+ x = x ? x : 0; y = y ? y : 0;
1323
+ if (isNullOrUndefined(this.panMove)) {
1324
+ this.panMove = {x: x, y: y};
1325
+ }
1326
+ if (isNullOrUndefined(this.tempPanMove)) {this.tempPanMove = {x: this.panMove.x, y: this.panMove.y}; }
1327
+ this.panEvent(x, y, true);
1328
+ this.tempPanMove = null;
1329
+ }
1330
+ } else {
1331
+ parent.togglePan = parent.currObjType.isCustomCrop = false;
1332
+ parent.notify('selection', {prop: 'setDragCanvas', value: {bool: false }});
1333
+ parent.lowerCanvas.style.cursor = parent.upperCanvas.style.cursor = parent.cursor = 'default';
1334
+ }
1335
+ }
1336
+ }
1337
+
1338
+ private zoom(zoomFactor: number, zoomPoint?: Point): void {
1339
+ const parent: ImageEditor = this.parent;
1340
+ if (!parent.disabled && parent.isImageLoaded) {
1341
+ const value: number = this.getCurrentZoomFactor(zoomFactor);
1342
+ if (isNullOrUndefined(zoomPoint)) {
1343
+ this.zoomAction(value, zoomPoint);
1344
+ } else {
1345
+ const type: string = value > 0 ? 'zoomIn' : 'zoomOut';
1346
+ const absValue: number = Math.abs(value) * 10;
1347
+ for (let i: number = 0; i < absValue; i++) {
1348
+ parent.notify('draw', { prop: 'performPointZoom', onPropertyChange: false,
1349
+ value: {x: zoomPoint.x, y: zoomPoint.y, type: type, isResize: null }});
1350
+ }
1351
+ }
1352
+ const actionArgs: EditCompleteEventArgs = { action: value > 0 ? 'zoom-in' : 'zoom-out',
1353
+ actionEventArgs: parent.editCompleteArgs };
1354
+ parent.triggerEditCompleteEvent(actionArgs);
1355
+ }
1356
+ }
1357
+
1358
+ private getCurrentZoomFactor(zoomFactor: number): number {
1359
+ return zoomFactor >= 1 ? (this.prevZoomValue < 1 ? (zoomFactor - this.prevZoomValue) : (zoomFactor - this.prevZoomValue) * 0.1) :
1360
+ (zoomFactor - this.prevZoomValue);
1361
+ }
1362
+
1363
+ private setCurrPanRegion(region: string, type: number | string, obj: Object): void {
1364
+ let panRegion: string = region;
1365
+ if (region === '') {
1366
+ panRegion = type === 'horizontal' ? 'horizontal' : type === 'vertical' ? 'vertical' : region;
1367
+ } else if (region === 'horizontal') {
1368
+ panRegion = type === 'horizontal' ? 'horizontalVertical' : type === 'vertical' ? 'verticalHorizontal' : type === 90 ?
1369
+ 'vertical' : type === -90 ? 'horizontal' : region;
1370
+ } else if (region === 'vertical') {
1371
+ panRegion = type === 'horizontal' ? 'horizontalVertical' : type === 'vertical' ? 'verticalHorizontal' : type === 90 ?
1372
+ 'horizontal' : type === -90 ? 'vertical' : region;
1373
+ } else {
1374
+ panRegion = type === 'horizontal' ? 'vertical' : type === 'vertical' ? 'horizontal' : region;
1375
+ }
1376
+ obj['panRegion'] = panRegion;
1377
+ }
1378
+
1379
+ private rotate(degree: number, obj: Object): void {
1380
+ const parent: ImageEditor = this.parent;
1381
+ const isRotate: boolean = false;
1382
+ if (!parent.disabled && parent.isImageLoaded && (degree % 90 === 0)) {
1383
+ this.rotateImage(degree);
1384
+ }
1385
+ obj['isRotate'] = isRotate;
1386
+ }
1387
+
1388
+ private flip(direction: Direction): void {
1389
+ const parent: ImageEditor = this.parent;
1390
+ if (!parent.disabled && parent.isImageLoaded) {
1391
+ this.flipImage(direction);
1392
+ }
1393
+ }
1394
+
1395
+ private update(): void {
1396
+ const parent: ImageEditor = this.parent; let toolbarHeight: number = 0;
1397
+ let isActiveObj: boolean = false; const freehandObj: Object = {bool: false };
1398
+ const straightenObj: Object = {bool: parent.isStraightening }; let cxtTbarHeight: number = 0;
1399
+ const ctToolbar: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_contextualToolbar');
1400
+ const ctWrapper: HTMLElement = parent.element.querySelector('.e-contextual-toolbar-wrapper');
1401
+ const hdWrapper: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_headWrapper');
1402
+ if (parent.isImageLoaded) {
1403
+ let isCropSelection: boolean = false; let splitWords: string[];
1404
+ if (Browser.isDevice) {
1405
+ if (parent.activeObj.shape) {splitWords = parent.activeObj.shape.split('-'); }
1406
+ if (parent.currObjType.isCustomCrop) {isCropSelection = true; }
1407
+ else if (splitWords && splitWords[0] === 'crop'){isCropSelection = true; }
1408
+ }
1409
+ const frameObj: Object = {bool: null };
1410
+ parent.notify('toolbar', { prop: 'getFrameToolbar', onPropertyChange: false, value: {obj: frameObj }});
1411
+ if (!straightenObj['bool'] && ((ctToolbar && !ctToolbar.parentElement.classList.contains('e-hide')) ||
1412
+ (hdWrapper && !hdWrapper.parentElement.classList.contains('e-hide')))) {
1413
+ ctWrapper.classList.add('e-hide');
1414
+ if (!isCropSelection) {parent.okBtn(null, true); }
1415
+ parent.notify('toolbar', { prop: 'refresh-main-toolbar', onPropertyChange: false});
1416
+ parent.notify('toolbar', { prop: 'destroy-qa-toolbar', onPropertyChange: false});
1417
+ }
1418
+ parent.notify('selection', { prop: 'getFreehandDrawEditing', onPropertyChange: false, value: {obj: freehandObj }});
1419
+ if (freehandObj['bool']) {
1420
+ parent.notify('toolbar', { prop: 'destroy-qa-toolbar', onPropertyChange: false});
1421
+ }
1422
+ const actPoint: ActivePoint = extend({}, parent.activeObj.activePoint, {}, true) as ActivePoint;
1423
+ if (parent.activeObj.shape && (actPoint.width !== 0 || actPoint.height !== 0)) {
1424
+ isActiveObj = true;
1425
+ if (parent.textArea.style.display === 'block' || parent.textArea.style.display === 'inline-block') {
1426
+ parent.notify('shape', { prop: 'redrawActObj', onPropertyChange: false,
1427
+ value: {x: null, y: null, isMouseDown: null}});
1428
+ parent.notify('toolbar', { prop: 'destroy-qa-toolbar', onPropertyChange: false});
1429
+ } else {
1430
+ parent.notify('shape', { prop: 'updImgRatioForActObj', onPropertyChange: false});
1431
+ parent.objColl.push(parent.activeObj);
1432
+ }
1433
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
1434
+ }
1435
+ }
1436
+ parent.updateDropInfoContent(parent.element.querySelector('.e-ie-drop-info'));
1437
+ const tempFilter: string = this.lowerContext.filter;
1438
+ const canvasWrapper: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_canvasWrapper');
1439
+ if (canvasWrapper) {
1440
+ canvasWrapper.style.width = parent.element.offsetWidth - 2 + 'px';
1441
+ }
1442
+ parent.lowerCanvas.width = parent.upperCanvas.width = parent.maskCanvas.width = parent.element.offsetWidth - 2;
1443
+ if (parent.toolbarTemplate) {
1444
+ toolbarHeight = parent.element.querySelector('#' + parent.element.id + '_toolbarArea').clientHeight;
1445
+ } else if (parent.element.querySelector('#' + parent.element.id + '_toolbar')) {
1446
+ toolbarHeight = parent.element.querySelector('#' + parent.element.id + '_toolbar').clientHeight;
1447
+ if (toolbarHeight === 0 && parent.toolbar && parent.toolbar.length > 0 && parent.toolbar.indexOf('Open') === -1) {
1448
+ const obj: Object = {toolbarHeight: 0 };
1449
+ parent.notify('toolbar', { prop: 'getToolbarHeight', value: {obj: obj }});
1450
+ toolbarHeight = obj['toolbarHeight'];
1451
+ }
1452
+ }
1453
+ const ctxTbarArea: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_contextualToolbarArea');
1454
+ if (Browser.isDevice && straightenObj['bool'] && ctxTbarArea) {
1455
+ cxtTbarHeight = ctxTbarArea.clientHeight;
1456
+ }
1457
+ parent.notify('toolbar', { prop: 'setToolbarHeight', value: {height: toolbarHeight }});
1458
+ if (Browser.isDevice) {
1459
+ if (canvasWrapper) {
1460
+ canvasWrapper.style.height = parent.element.offsetHeight - ((2 * toolbarHeight) + cxtTbarHeight) - 4 + 'px';
1461
+ }
1462
+ } else {
1463
+ if (canvasWrapper) {
1464
+ canvasWrapper.style.height = parent.element.offsetHeight - toolbarHeight - 2 + 'px';
1465
+ }
1466
+ }
1467
+ parent.lowerCanvas.height = parent.upperCanvas.height = parseFloat(canvasWrapper.style.height);
1468
+ this.lowerContext.filter =
1469
+ 'brightness(' + 1 + ') ' + 'contrast(' + 100 + '%) ' + 'hue-rotate(' + 0 + 'deg) ' +
1470
+ 'saturate(' + 100 + '%) ' + 'opacity(' + 1 + ') ' + 'blur(' + 0 + 'px) ' + 'sepia(0%) ' + 'grayscale(0%) ' + 'invert(0%)';
1471
+ parent.notify('filter', { prop: 'setAdjustmentValue', onPropertyChange: false, value: {adjustmentValue: this.lowerContext.filter }});
1472
+ parent.canvasFilter = this.lowerContext.filter; parent.initialAdjustmentValue = this.lowerContext.filter;
1473
+ parent.clearContext(this.lowerContext); parent.clearContext(this.upperContext);
1474
+ if (parent.isImageLoaded) {
1475
+ parent.notify('shape', { prop: 'applyActObj', onPropertyChange: false, value: {isMouseDown: null}});
1476
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
1477
+ this.lowerContext.filter = tempFilter; parent.initialAdjustmentValue = tempFilter;
1478
+ parent.canvasFilter = this.lowerContext.filter;
1479
+ if (parent.isImageLoaded) {
1480
+ showSpinner(parent.element);
1481
+ parent.element.style.opacity = '0.5';
1482
+ }
1483
+ this.lowerContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
1484
+ this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
1485
+ if (canvasWrapper) {
1486
+ canvasWrapper.style.width = parent.element.offsetWidth - 2 + 'px';
1487
+ canvasWrapper.style.height = parent.element.offsetHeight + 'px';
1488
+ const obj: Object = {toolbarHeight: 0 };
1489
+ parent.notify('toolbar', { prop: 'getToolbarHeight', value: {obj: obj }});
1490
+ if (Browser.isDevice) {
1491
+ canvasWrapper.style.height = (parseFloat(canvasWrapper.style.height) - (2 * obj['toolbarHeight']) - cxtTbarHeight) - 4 + 'px';
1492
+ } else {
1493
+ canvasWrapper.style.height = (parseFloat(canvasWrapper.style.height) - obj['toolbarHeight']) - 2 + 'px';
1494
+ }
1495
+
1496
+ }
1497
+ parent.lowerCanvas.width = parent.upperCanvas.width = parent.maskCanvas.width =
1498
+ parseFloat(canvasWrapper.style.width);
1499
+ parent.lowerCanvas.height = parent.upperCanvas.height = parent.maskCanvas.height =
1500
+ parseFloat(canvasWrapper.style.height);
1501
+ this.lowerContext.filter = tempFilter;
1502
+ this.lowerContext.imageSmoothingQuality = parent.imageSmoothingEnabled ? 'high' : 'low';
1503
+ const obj: Object = {width: 0, height: 0 };
1504
+ this.calcMaxDimension(parent.img.srcWidth, parent.img.srcHeight, obj);
1505
+ const maxDimension: Dimension = obj as Dimension;
1506
+ if (straightenObj['bool'] && parent.transform.cropZoomFactor !== 0) {
1507
+ maxDimension.width += (maxDimension.width * parent.transform.cropZoomFactor);
1508
+ maxDimension.height += (maxDimension.height * parent.transform.cropZoomFactor);
1509
+ } else if (parent.transform.defaultZoomFactor > 0) {
1510
+ maxDimension.width += (maxDimension.width * parent.transform.defaultZoomFactor);
1511
+ maxDimension.height += (maxDimension.height * parent.transform.defaultZoomFactor);
1512
+ }
1513
+ parent.img.destLeft = (parent.lowerCanvas.clientWidth - maxDimension.width) / 2;
1514
+ parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height) / 2;
1515
+ if (parent.transform.degree === 0 && parent.transform.currFlipState === '') {
1516
+ if (parent.transform.defaultZoomFactor > 0) {
1517
+ parent.img.destLeft += parent.panPoint.totalPannedPoint.x;
1518
+ parent.img.destTop += parent.panPoint.totalPannedPoint.y;
1519
+ }
1520
+ parent.notify('draw', {prop: 'draw-image-to-canvas', value: {dimension: maxDimension } });
1521
+ } else {
1522
+ parent.notify('draw', {prop: 'draw-image-to-canvas', value: {dimension: maxDimension } });
1523
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
1524
+ value: {type: 'initial', isPreventDestination: null, isRotatePan: null} });
1525
+ const temp: string = this.lowerContext.filter;
1526
+ parent.notify('draw', { prop: 'drawImage', onPropertyChange: false});
1527
+ this.lowerContext.filter = temp;
1528
+ parent.notify('draw', { prop: 'updateCurrTransState', onPropertyChange: false,
1529
+ value: {type: 'reverse', isPreventDestination: null, isRotatePan: null} });
1530
+ }
1531
+ parent.notify('shape', { prop: 'drawAnnotations', onPropertyChange: false,
1532
+ value: {ctx: this.lowerContext, shape: 'zoom', pen: 'zoom', isPreventApply: null }});
1533
+ parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.lowerContext}});
1534
+ parent.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: {context: this.upperContext}});
1535
+ if (parent.isCircleCrop) {
1536
+ parent.notify('crop', { prop: 'cropCircle', onPropertyChange: false,
1537
+ value: {context: this.lowerContext, isSave: null, isFlip: null}});
1538
+ }
1539
+ hideSpinner(parent.element); parent.element.style.opacity = '1';
1540
+ const obj1: Object = {defToolbarItems : null };
1541
+ parent.notify('toolbar', { prop: 'getDefToolbarItems', value: {obj: obj1 }});
1542
+ if (obj1['defToolbarItems'] && obj1['defToolbarItems'].length > 0 && document.getElementById(parent.element.id + '_toolbar')) {
1543
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
1544
+ const toolbar: any = getComponent(parent.element.id + '_toolbar', 'toolbar') as Toolbar;
1545
+ if (toolbar) {toolbar.refreshOverflow(); }
1546
+ if (ctWrapper && !straightenObj['bool']) {
1547
+ ctWrapper.classList.add('e-hide');
1548
+ }
1549
+ }
1550
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false});
1551
+ this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
1552
+ if (isActiveObj) {
1553
+ let activeObj: SelectionPoint = extend({}, parent.objColl[parent.objColl.length - 1], null, true) as SelectionPoint;
1554
+ parent.objColl.pop();
1555
+ if (activeObj.activePoint.width !== 0 && activeObj.activePoint.height !== 0) {
1556
+ this.lowerContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
1557
+ parent.notify('draw', {prop: 'render-image', value: {isMouseWheel: null }});
1558
+ parent.objColl.push(activeObj);
1559
+ parent.notify('shape', { prop: 'drawAnnotations', onPropertyChange: false,
1560
+ value: {ctx: this.lowerContext, shape: 'zoom', pen: 'zoom', isPreventApply: null }});
1561
+ activeObj = extend({}, parent.objColl[parent.objColl.length - 1], null, true) as SelectionPoint;
1562
+ parent.objColl.pop();
1563
+ this.lowerContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
1564
+ parent.notify('draw', {prop: 'render-image', value: {isMouseWheel: null }});
1565
+ parent.notify('draw', { prop: 'drawObject', onPropertyChange: false, value: {canvas: 'duplicate', obj: activeObj}});
1566
+ if (straightenObj['bool']) {
1567
+ parent.notify('draw', { prop: 'setStraightenActObj', value: {activeObj: activeObj }});
1568
+ }
1569
+ if (parent.activeObj.shape === 'rectangle' || parent.activeObj.shape === 'ellipse' || parent.activeObj.shape === 'text' ||
1570
+ parent.activeObj.shape === 'line' || parent.activeObj.shape === 'arrow' || parent.activeObj.shape === 'path' ||
1571
+ parent.activeObj.shape === 'image') {
1572
+ parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: {isPenEdit: null} });
1573
+ }
1574
+ }
1575
+ }
1576
+ if (freehandObj['bool']) {
1577
+ parent.notify('toolbar', { prop: 'renderQAT', onPropertyChange: false, value: {isPenEdit: true} });
1578
+ }
1579
+ if (parent.isResize) {
1580
+ parent.aspectWidth = Math.ceil(parent.img.destWidth); parent.aspectHeight = Math.ceil(parent.img.destHeight);
1581
+ parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'resize',
1582
+ isApplyBtn: false, isCropping: false }});
1583
+ parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'resize',
1584
+ isApplyBtn: false, isCropping: false }});
1585
+ }
1586
+ if ((parent.transform.degree !== 0 || parent.transform.currFlipState !== '') && parent.transform.defaultZoomFactor > 0) {
1587
+ const totalPannedPoint: Point = extend({}, parent.panPoint.totalPannedPoint, null, true) as Point;
1588
+ const totalPannedInternalPoint: Point = extend({}, parent.panPoint.totalPannedInternalPoint, null, true) as Point;
1589
+ const totalPannedClientPoint: Point = extend({}, parent.panPoint.totalPannedClientPoint, null, true) as Point;
1590
+ this.zoomAction(.1);
1591
+ this.zoomAction(-.1);
1592
+ if (parent.transform.degree === 0) {
1593
+ parent.img.destLeft += totalPannedPoint.x; parent.img.destTop += totalPannedPoint.y;
1594
+ parent.panPoint.totalPannedPoint = totalPannedPoint;
1595
+ parent.notify('draw', {prop: 'updateFlipPan', value: {tempSelectionObj: null}});
1596
+ } else {
1597
+ parent.panPoint.totalPannedInternalPoint = totalPannedInternalPoint;
1598
+ parent.panPoint.totalPannedClientPoint = totalPannedClientPoint;
1599
+ parent.panPoint.currentPannedPoint = {x: 0, y: 0};
1600
+ parent.isCropTab = true;
1601
+ this.rotatePan();
1602
+ parent.isCropTab = false;
1603
+ }
1604
+ } else if (parent.transform.degree !== 0 && parent.transform.cropZoomFactor > 0) {
1605
+ parent.transform.zoomFactor = 0; parent.transform.cropZoomFactor = null;
1606
+ parent.notify('toolbar', { prop: 'enable-disable-btns', onPropertyChange: false});
1607
+ }
1608
+ }
1609
+ }
1610
+
1611
+ private calcMaxDimension(width: number, height: number, obj?: Object, isImgShape?: boolean): Dimension {
1612
+ const object: Object = {toolbarHeight: 0 }; const parent: ImageEditor = this.parent;
1613
+ parent.notify('toolbar', { prop: 'getToolbarHeight', value: {obj: object }});
1614
+ const newWidth: number = parent.imageSettings.width ? parent.imageSettings.width : parent.element.clientWidth;
1615
+ const newHeight: number = parent.imageSettings.height ? parent.imageSettings.height : parent.element.clientHeight - (object['toolbarHeight']);
1616
+ let canvasMaxWidth: number = isImgShape ? parent.element.clientWidth / 3 : newWidth;
1617
+ let canvasMaxHeight: number = isImgShape ? (parent.element.clientHeight - object['toolbarHeight']) / 3 : newHeight;
1618
+ canvasMaxHeight = Browser.isDevice ? canvasMaxHeight - (object['toolbarHeight']) : canvasMaxHeight;
1619
+ if (Browser.isDevice && parent.isStraightening) {
1620
+ const cxtTbar: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_contextualToolbarArea');
1621
+ canvasMaxHeight -= cxtTbar ? cxtTbar.clientHeight : 0;
1622
+ }
1623
+ if (!isImgShape && parent.element.clientHeight === 0) {
1624
+ canvasMaxHeight = 0;
1625
+ }
1626
+ const isImageSettings: boolean = parent.imageSettings.width && parent.imageSettings.height ? true : false;
1627
+ if (isNullOrUndefined(isImgShape) && !(isImageSettings)) {
1628
+ if (canvasMaxWidth > 30) {canvasMaxWidth -= 30; } if (canvasMaxHeight > 30) {canvasMaxHeight -= 30; }
1629
+ }
1630
+ const widthScale: number = canvasMaxWidth / width; const heightScale: number = canvasMaxHeight / height;
1631
+ let cssMaxWidth: number = Math.min(width, canvasMaxWidth); let cssMaxHeight: number = Math.min(height, canvasMaxHeight);
1632
+ if (widthScale < 1 && widthScale < heightScale) {
1633
+ cssMaxWidth = width * widthScale; cssMaxHeight = height * widthScale;
1634
+ }
1635
+ else if (heightScale < 1 && heightScale < widthScale) {cssMaxWidth = width * heightScale; cssMaxHeight = height * heightScale; }
1636
+ if (isNullOrUndefined(isImgShape)) {
1637
+ const cropObj: Object = {bool: null };
1638
+ parent.notify('crop', { prop: 'getPreventScaling', onPropertyChange: false,
1639
+ value: {obj: cropObj }});
1640
+ if (cropObj['bool'] && parent.cropObj.activeObj.activePoint &&
1641
+ parent.cropObj.activeObj.activePoint.width !== 0 && parent.cropObj.activeObj.activePoint.height !== 0) {
1642
+ cssMaxWidth = parent.cropObj.activeObj.activePoint.width;
1643
+ cssMaxHeight = parent.cropObj.activeObj.activePoint.height;
1644
+ }
1645
+ }
1646
+ if (obj) {obj['width'] = cssMaxWidth; obj['height'] = cssMaxHeight; }
1647
+ return {width: cssMaxWidth, height: cssMaxHeight};
1648
+ }
1649
+
1650
+ private updatePanPoints(x?: number, y?: number): Point {
1651
+ const parent: ImageEditor = this.parent;
1652
+ const tempActObj: SelectionPoint = extend({}, parent.activeObj, {}, true) as SelectionPoint;
1653
+ const tempDestLeft: number = parent.img.destLeft; const tempDestTop: number = parent.img.destTop;
1654
+ if (isNullOrUndefined(this.tempPanMove)) {this.tempPanMove = {x: this.panMove.x, y: this.panMove.y}; }
1655
+ let xDiff: number = this.panMove.x - this.tempPanMove.x; let yDiff: number = this.panMove.y - this.tempPanMove.y;
1656
+ if (x || y) {xDiff = x; yDiff = y; }
1657
+ parent.img.destLeft += xDiff; parent.img.destTop += yDiff;
1658
+ this.limitPan();
1659
+ const obj: Object = {bool: null };
1660
+ const object: Object = {isIntersect: null };
1661
+ parent.notify('draw', { prop: 'updateImgCanvasPoints', onPropertyChange: false });
1662
+ parent.notify('draw', { prop: 'isLinesIntersect', onPropertyChange: false, value: {obj: object }});
1663
+ parent.notify('draw', { prop: 'isSelOutsideImg', onPropertyChange: false, value: {obj: obj }});
1664
+ let count: number = 0;
1665
+ while (parent.transform.straighten !== 0 && (object['isIntersect'] || obj['bool'])) {
1666
+ count++;
1667
+ parent.img.destLeft = tempDestLeft; parent.img.destTop = tempDestTop;
1668
+ if (xDiff !== 0 && xDiff > 0) {xDiff -= 1; } else if (xDiff !== 0 && xDiff < 0) {xDiff += 1; }
1669
+ if (yDiff !== 0 && yDiff > 0) {yDiff -= 1; } else if (yDiff !== 0 && yDiff < 0) {yDiff += 1; }
1670
+ if ((xDiff === 0 && yDiff === 0) || count === 200) {
1671
+ break;
1672
+ }
1673
+ parent.img.destLeft += xDiff; parent.img.destTop += yDiff;
1674
+ this.limitPan();
1675
+ parent.notify('draw', { prop: 'updateImgCanvasPoints', onPropertyChange: false });
1676
+ parent.notify('draw', { prop: 'isLinesIntersect', onPropertyChange: false, value: { obj: object } });
1677
+ parent.notify('draw', { prop: 'isSelOutsideImg', onPropertyChange: false, value: { obj: obj } });
1678
+ }
1679
+ parent.activeObj = tempActObj;
1680
+ return {x: parent.img.destLeft - tempDestLeft, y: parent.img.destTop - tempDestTop};
1681
+ }
1682
+
1683
+ private resizeImage(width?: number, height?: number): void {
1684
+ const parent: ImageEditor = this.parent; let temp: boolean = true; let temp1: boolean = true;
1685
+ parent.allowDownScale = false;
1686
+ parent.img.srcLeft = 0; parent.img.srcTop = 0; parent.isAspectRatio = true; const minimum: number[] = [];
1687
+ parent.img.srcWidth = parent.baseImgCanvas.width; parent.img.srcHeight = parent.baseImgCanvas.height;
1688
+ if (parent.resizeSrc && parent.resizeSrc.width !== 0 && parent.resizeSrc.height !== 0) {
1689
+ parent.img.srcLeft = parent.resizeSrc.startX; parent.img.srcTop = parent.resizeSrc.startY;
1690
+ parent.img.srcWidth = parent.resizeSrc.width; parent.img.srcHeight = parent.resizeSrc.height;
1691
+ }
1692
+ while ((width < parent.img.destWidth || height < parent.img.destHeight) && temp1) {
1693
+ this.zoomAction(-.1, null, true, true);
1694
+ if (width > parent.img.destWidth || height > parent.img.destHeight) {
1695
+ while (width > parent.img.destWidth || height > parent.img.destHeight) {
1696
+ this.zoomAction(0.0125, null, true, true);
1697
+ temp1 = false;
1698
+ minimum.push(parent.img.destWidth);
1699
+ }
1700
+ }
1701
+ }
1702
+ while ((width > parent.img.destWidth || height > parent.img.destHeight) && temp1 && temp) {
1703
+ this.zoomAction(.1, null, true, true);
1704
+ if (width < parent.img.destWidth || height < parent.img.destHeight) {
1705
+ while (width < parent.img.destWidth) {
1706
+ this.zoomAction(-.0125, null, true, true);
1707
+ temp = false;
1708
+ minimum.push(parent.img.destWidth);
1709
+ }
1710
+ }
1711
+ }
1712
+ let nearestNumber: number = minimum[0]; let smallestDifference: number = Math.abs(parent.img.destWidth - nearestNumber);
1713
+ for (const num of minimum) {
1714
+ const difference: number = Math.abs(width - num);
1715
+ if (difference < smallestDifference) {
1716
+ nearestNumber = num; smallestDifference = difference;
1717
+ }
1718
+ }
1719
+ if (nearestNumber < width && temp) {
1720
+ this.zoomAction(-.0125, null, true, true); temp = false;
1721
+ }
1722
+ if (nearestNumber > width && !temp) {
1723
+ this.zoomAction(.0125, null, true, true); temp = false;
1724
+ }
1725
+ this.zoomAction(.0125, null, true); parent.allowDownScale = true; this.zoomAction(-.0125, null, true);
1726
+ const prevCropObj: CurrentObject = extend({}, parent.cropObj, {}, true) as CurrentObject;
1727
+ const prevObj: CurrentObject = extend({}, this.prevResizeCurrObj, {}, true) as CurrentObject;
1728
+ parent.notify('undo-redo', { prop: 'updateUndoRedoColl', onPropertyChange: false, value: { operation: 'resize',
1729
+ previousObj: prevObj, previousObjColl: prevObj.objColl, previousPointColl: prevObj.pointColl,
1730
+ previousSelPointColl: prevObj.selPointColl, previousCropObj: prevCropObj, previousText: null, currentText: null,
1731
+ previousFilter: null, isCircleCrop: parent.isCircleCrop }});
1732
+ parent.notify('undo-redo', { prop: 'updateCurrUrc', value: { type: 'ok' } });
1733
+ }
1734
+
1735
+ private resizeCrop(width?: number, height?: number): void {
1736
+ const parent: ImageEditor = this.parent; let temp: boolean = true;
1737
+ const obj1: object = {prevObj: parent.prevObj};
1738
+ parent.cropObj = extend({}, parent.prevCropObj, {}, true) as CurrentObject;
1739
+ parent.allowDownScale = false;
1740
+ parent.notify('toolbar', { prop: 'getPrevObj', onPropertyChange: false, value: { obj: obj1 } });
1741
+ const activeObj: SelectionPoint = extend({}, obj1['prevObj']['activeObj'], {}, true) as SelectionPoint;
1742
+ obj1['prevObj']['activeObj'] = extend({}, parent.activeObj, {}, true) as SelectionPoint;
1743
+ parent.notify('draw', { prop: 'setCurrentObj', onPropertyChange: false, value: { obj: obj1['prevObj'] }});
1744
+ parent.objColl = extend([], obj1['prevObj']['objColl'], [], true) as SelectionPoint[];
1745
+ parent.pointColl = extend([], obj1['prevObj']['pointColl'], [], true) as Point[];
1746
+ parent.transform.straighten = 0;
1747
+ parent.notify('shape', { prop: 'drawAnnotations', onPropertyChange: false,
1748
+ value: {ctx: this.lowerContext, shape: 'zoom', pen: 'zoom', isPreventApply: null }});
1749
+ if (parent.transform.straighten === 0 && !this.isPreventSelect) {
1750
+ parent.notify('freehand-draw', { prop: 'updateFHDColl', onPropertyChange: false});
1751
+ }
1752
+ const tempwidth: number = width; const tempheight: number = height; let tempZoom: boolean = false;
1753
+ if (height >= width && height <= Math.ceil(parent.img.destHeight)) {
1754
+ while ((height <= Math.ceil(parent.img.destHeight)) && temp) {
1755
+ this.zoomAction(-.1, null, true, true);
1756
+ if (width > parent.img.destWidth || height > parent.img.destHeight) {
1757
+ while (width > parent.img.destWidth || height > parent.img.destHeight) {
1758
+ this.zoomAction(.0125, null, true, true); temp = false;
1759
+ }
1760
+ }
1761
+ }
1762
+ } else if (height <= width && width < parent.img.destWidth) {
1763
+ while ((width < parent.img.destWidth) && temp) {
1764
+ this.zoomAction(-.1, null, true, true);
1765
+ if (width > parent.img.destWidth || height > parent.img.destHeight) {
1766
+ while (width > parent.img.destWidth || height > parent.img.destHeight) {
1767
+ this.zoomAction(.0125, null, true, true); temp = false;
1768
+ }
1769
+ }
1770
+ }
1771
+ } else if (height >= width && height >= parent.img.destHeight) {
1772
+ while ((height >= parent.img.destHeight) && temp) {
1773
+ this.zoomAction(.1, null, true, true);
1774
+ }
1775
+ } else if (width >= height && width >= parent.img.destWidth) {
1776
+ while ((width >= parent.img.destWidth) && temp) {
1777
+ this.zoomAction(.1, null, true, true);
1778
+ }
1779
+ if (width < parent.img.destWidth && height < parent.img.destHeight) {
1780
+ while (width < parent.img.destWidth && height < parent.img.destHeight) {
1781
+ this.zoomAction(-.0125, null, true, true);
1782
+ temp = false;
1783
+ }
1784
+ this.zoomAction(.0125, null, true, true);
1785
+ }
1786
+ } else if (height > parent.img.destHeight && width > parent.img.destWidth ) {
1787
+ while ((height > parent.img.destHeight) && (width > parent.img.destWidth) && temp) {
1788
+ this.zoomAction(.1, null, true, true);
1789
+ }
1790
+ if (width < parent.img.destWidth && height < parent.img.destHeight) {
1791
+ while (width < parent.img.destWidth && height < parent.img.destHeight) {
1792
+ this.zoomAction(-.0125, null, true, true);
1793
+ temp = false;
1794
+ }
1795
+ this.zoomAction(.0125, null, true, true);
1796
+ }
1797
+ }
1798
+ if (parent.isPublicMethod && parent.aspectWidth === width && parent.aspectHeight === height) {
1799
+ return;
1800
+ }
1801
+ this.resizeImg(activeObj, width, height); width = tempwidth; height = tempheight;
1802
+ if ((height !== parent.img.destHeight || width !== parent.img.destWidth)) {
1803
+ while ((height > parent.img.destHeight || width > parent.img.destWidth)) {
1804
+ this.zoomAction(.0125, null, true, true); tempZoom = true;
1805
+ }
1806
+ if (tempZoom) {
1807
+ this.zoomAction(-.0125, null, true, true); tempZoom = false;
1808
+ }
1809
+ }
1810
+ if ((height !== parent.img.destHeight || width !== parent.img.destWidth)) {
1811
+ while ((height < parent.img.destHeight || width < parent.img.destWidth)) {
1812
+ this.zoomAction(-.0125, null, true, true); tempZoom = true;
1813
+ }
1814
+ if (tempZoom) {
1815
+ this.zoomAction(-.0125, null, true, true); tempZoom = false;
1816
+ }
1817
+ }
1818
+ obj1['prevObj']['activeObj'] = extend({}, activeObj, {}, true) as SelectionPoint;
1819
+ this.zoomAction(.0125, null, true);
1820
+ parent.allowDownScale = this.preventDownScale ? false : true; parent.isCropTab = false;
1821
+ this.zoomAction(-.0125, null, true);
1822
+ parent.aspectWidth = width; parent.aspectHeight = height;
1823
+ }
1824
+
1825
+ private resizeImg(activeObj: SelectionPoint, width: number, height: number): void {
1826
+ const parent: ImageEditor = this.parent; const widthRatio: number = width / parent.img.destWidth;
1827
+ const heightRatio: number = height / parent.img.destHeight;
1828
+ if (activeObj.shape) {
1829
+ parent.currSelectionPoint = activeObj;
1830
+ parent.notify('crop', { prop: 'setInitCrop', onPropertyChange: false, value: {bool: true}});
1831
+ } else if (parent.img.srcWidth === parent.baseImgCanvas.width && parent.img.srcHeight === parent.baseImgCanvas.height) {
1832
+ parent.currSelectionPoint = null;
1833
+ parent.notify('draw', { prop: 'select', onPropertyChange: false,
1834
+ value: {type: 'custom', startX: null, startY: null, width: null, height: null }});
1835
+ }
1836
+ if (isNullOrUndefined(parent.currSelectionPoint)) {
1837
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
1838
+ if (!parent.shapeColl.some((item: any) => item.rotatedAngle && item.rotatedAngle !== 0)) {
1839
+ parent.notify('draw', { prop: 'select', onPropertyChange: false,
1840
+ value: {type: 'custom', startX: parent.img.destLeft, startY: parent.img.destTop,
1841
+ width: parent.img.destWidth, height: parent.img.destHeight }});
1842
+ }
1843
+ } else {
1844
+ parent.notify('draw', { prop: 'select', onPropertyChange: false,
1845
+ value: {type: 'custom', startX: null, startY: null, width: null, height: null}});
1846
+ }
1847
+ width = parent.activeObj.activePoint.width * widthRatio;
1848
+ height = parent.activeObj.activePoint.height * heightRatio;
1849
+ let sx: number = (parent.activeObj.activePoint.startX + (parent.activeObj.activePoint.width / 2)) - (width / 2);
1850
+ let sy: number = (parent.activeObj.activePoint.startY + (parent.activeObj.activePoint.height / 2)) - (height / 2);
1851
+ let count: number = 0;
1852
+ while (Browser.isDevice && count < 500 && (sx < 0 || sy < 0 || (sx + width) > parent.img.destWidth
1853
+ || (sy + height) > parent.img.destHeight)) {
1854
+ count++;
1855
+ width -= 1; height -= 1;
1856
+ sx = (parent.activeObj.activePoint.startX + (parent.activeObj.activePoint.width / 2)) - (width / 2);
1857
+ sy = (parent.activeObj.activePoint.startY + (parent.activeObj.activePoint.height / 2)) - (height / 2);
1858
+ }
1859
+ parent.transform.defaultZoomFactor = 0;
1860
+ parent.notify('draw', {prop: 'setResizeSelect', value: {bool: true }});
1861
+ parent.notify('draw', {prop: 'setIsCropSelect', value: {bool: true }});
1862
+ parent.notify('draw', { prop: 'select', onPropertyChange: false,
1863
+ value: {type: 'custom', startX: sx, startY: sy, width: width, height: height}});
1864
+ parent.notify('draw', {prop: 'setResizeSelect', value: {bool: false }});
1865
+ if (parent.transform.straighten !== 0) {
1866
+ const obj: Object = {isIntersect: null, arr: null };
1867
+ parent.notify('draw', { prop: 'updateImgCanvasPoints', onPropertyChange: false });
1868
+ parent.notify('draw', { prop: 'isLinesIntersect', onPropertyChange: false, value: {obj: obj }});
1869
+ while (obj['arr'][0] || obj['arr'][1] || obj['arr'][2] || obj['arr'][3]) {
1870
+ this.zoomAction(.0125, null, true);
1871
+ parent.notify('draw', { prop: 'updateImgCanvasPoints', onPropertyChange: false });
1872
+ parent.notify('draw', { prop: 'isLinesIntersect', onPropertyChange: false, value: {obj: obj }});
1873
+ }
1874
+ }
1875
+ parent.isCropToolbar = true;
1876
+ parent.crop();
1877
+ parent.isCropToolbar = false;
1878
+ }
1879
+
1880
+ private updateResize(): void {
1881
+ const parent: ImageEditor = this.parent;
1882
+ parent.prevCropObj = extend({}, parent.cropObj, {}, true) as CurrentObject;
1883
+ const currObject: Object = {currObj: {} as CurrentObject };
1884
+ parent.notify('filter', { prop: 'getCurrentObj', onPropertyChange: false, value: {object: currObject }});
1885
+ parent.prevObj = currObject['currObj'];
1886
+ if (parent.currSelectionPoint && parent.prevCropObj.activeObj.shape) {
1887
+ parent.prevObj.activeObj = extend({}, parent.prevCropObj.activeObj, {}, true) as SelectionPoint;
1888
+ }
1889
+ parent.prevObj.objColl = extend([], parent.objColl, [], true) as SelectionPoint[];
1890
+ parent.prevObj.pointColl = extend([], parent.pointColl, [], true) as Point[];
1891
+ parent.prevObj.afterCropActions = extend([], parent.afterCropActions, [], true) as string[];
1892
+ const selPointCollObj: Object = {selPointColl: null };
1893
+ parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
1894
+ value: {obj: selPointCollObj }});
1895
+ parent.prevObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true) as Point[];
1896
+ parent.resizeSrc = {startX: parent.img.srcLeft, startY: parent.img.srcTop, width: parent.img.srcWidth,
1897
+ height: parent.img.srcHeight };
1898
+ }
1899
+
1900
+ private resize(width: number, height: number, isAspectRatio?: boolean): void {
1901
+ const parent: ImageEditor = this.parent;
1902
+ let aspectHeight: string;
1903
+ parent.isResize = true;
1904
+ if (isNullOrUndefined(parent.prevCropObj) && isNullOrUndefined(parent.prevObj)) {
1905
+ parent.notify('transform', { prop: 'updateResize', value: {bool: false }});
1906
+ }
1907
+ const aspectIcon: HTMLInputElement = (parent.element.querySelector('#' + parent.element.id + '_aspectratio') as HTMLInputElement);
1908
+ const nonAspectIcon: HTMLInputElement = (parent.element.querySelector('#' + parent.element.id + '_nonaspectratio') as HTMLInputElement);
1909
+ if (aspectIcon && nonAspectIcon) {
1910
+ parent.notify('toolbar', { prop: 'initResizeToolbar'});
1911
+ if (Browser.isDevice) {
1912
+ parent.notify('toolbar', { prop: 'init-main-toolbar', value: {isApplyBtn: false, isDevice: true, isOkBtn: true, isResize: true}});
1913
+ }
1914
+ }
1915
+ const aspectRatioHeight: HTMLInputElement = parent.element.querySelector('#' + parent.element.id + '_resizeHeight');
1916
+ if (aspectRatioHeight) {
1917
+ aspectHeight = aspectRatioHeight.value === '' ? aspectRatioHeight.placeholder : aspectRatioHeight.value;
1918
+ } else {
1919
+ aspectHeight = height + 'px';
1920
+ }
1921
+ const resizeEventArgs: ResizeEventArgs = {cancel: false, previousWidth: Math.ceil(parent.img.destWidth),
1922
+ previousHeight: Math.ceil(parent.img.destHeight), width: Math.ceil(width), height: height && height !== 0 ? Math.ceil(height) :
1923
+ (isAspectRatio ? Math.ceil(parseFloat(aspectHeight)) : Math.ceil(parent.img.destHeight)),
1924
+ isAspectRatio: isAspectRatio ? isAspectRatio : false };
1925
+ parent.trigger('resizing', resizeEventArgs);
1926
+ parent.editCompleteArgs = resizeEventArgs;
1927
+ if (!resizeEventArgs.cancel) {
1928
+ this.resizeEventHandler(resizeEventArgs);
1929
+ } else if (parent.aspectHeight && parent.aspectWidth) {
1930
+ parent.aspectHeight = resizeEventArgs.previousHeight; parent.aspectWidth = resizeEventArgs.previousWidth;
1931
+ }
1932
+ }
1933
+
1934
+ private resizeEventHandler(args: ResizeEventArgs): void {
1935
+ const parent: ImageEditor = this.parent; let isRotate: boolean;
1936
+ const aspectRatioWidth: HTMLInputElement = parent.element.querySelector('#' + parent.element.id + '_resizeWidth');
1937
+ const aspectRatioHeight: HTMLInputElement = parent.element.querySelector('#' + parent.element.id + '_resizeHeight');
1938
+ if (args.isAspectRatio) {
1939
+ if (this.resizedImgAngle == null || this.resizedImgAngle !== parent.transform.degree) {
1940
+ this.resizedImgAngle = parent.transform.degree;
1941
+ isRotate = true;
1942
+ }
1943
+ if (isRotate) {
1944
+ parent.notify('transform', { prop: 'resizeImage', value: { width: args.width, height: 0 } });
1945
+ const originalWidth: number = parent.img.destWidth;
1946
+ const originalHeight: number = parent.img.destHeight;
1947
+ let aspectRatioWidthValue: number;
1948
+ if (aspectRatioHeight) {
1949
+ aspectRatioWidthValue = parseFloat(aspectRatioWidth.value === '' ? aspectRatioWidth.placeholder : aspectRatioWidth.value);
1950
+ let value: number = aspectRatioWidthValue / (originalWidth / originalHeight);
1951
+ // eslint-disable-next-line max-len
1952
+ const height: number = value % 1 >= 0.5 || value % 1 <= -0.5 ? Math.round(value) : (value < 0) ? Math.ceil(value) : Math.floor(value);
1953
+ (getComponent(aspectRatioHeight, 'numerictextbox') as NumericTextBox).value = height;
1954
+ (aspectRatioHeight as HTMLInputElement).value = height.toString() + ' px';
1955
+ parent.aspectHeight = height;
1956
+ if (aspectRatioWidth && (aspectRatioWidth as HTMLInputElement).value === '') {
1957
+ const aspectRatioHeightValue: number = parseFloat(aspectRatioHeight.value === '' ? aspectRatioHeight.placeholder :
1958
+ aspectRatioHeight.value);
1959
+ value = aspectRatioHeightValue / (originalHeight / originalWidth);
1960
+ // eslint-disable-next-line max-len
1961
+ const width: number = value % 1 >= 0.5 || value % 1 <= -0.5 ? Math.round(value) : (value < 0) ? Math.ceil(value) : Math.floor(value);
1962
+ (getComponent(aspectRatioWidth, 'numerictextbox') as NumericTextBox).value = width;
1963
+ (aspectRatioWidth as HTMLInputElement).value = width.toString() + ' px';
1964
+ parent.aspectWidth = width;
1965
+ }
1966
+ }
1967
+ } else {
1968
+ parent.notify('transform', { prop: 'resizeImage', value: { width: args.width, height: null } });
1969
+ }
1970
+ } else {
1971
+ if (this.resizedImgAngle !== null && this.resizedImgAngle !== parent.transform.degree) {
1972
+ this.resizedImgAngle = parent.transform.degree;
1973
+ isRotate = true;
1974
+ }
1975
+ if (isRotate) {
1976
+ parent.notify('transform', { prop: 'setPreventDownScale', value: { bool: true } });
1977
+ parent.notify('transform', { prop: 'resizeCrop', value: { width: args.width, height: args.height } });
1978
+ parent.notify('undo-redo', { prop: 'setPreventUR', value: { bool: true } });
1979
+ parent.okBtn(null, true);
1980
+ parent.notify('undo-redo', { prop: 'setPreventUR', value: { bool: false } });
1981
+ parent.resizeSrc = { startX: parent.img.srcLeft, startY: parent.img.srcTop, width: parent.img.srcWidth,
1982
+ height: parent.img.srcHeight };
1983
+ parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'resize',
1984
+ isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
1985
+ parent.notify('transform', { prop: 'setPreventDownScale', value: { bool: false } });
1986
+ parent.notify('toolbar', { prop: 'refresh-toolbar', onPropertyChange: false, value: {type: 'resize',
1987
+ isApplyBtn: null, isCropping: null, isZooming: null, cType: null}});
1988
+ } else {
1989
+ parent.notify('transform', { prop: 'resizeCrop', value: { width: args.width, height: args.height } });
1990
+ }
1991
+ }
1992
+ this.resizedImgAngle = parent.transform.degree;
1993
+ }
1994
+
1995
+ private straightenImage(degree: number): void {
1996
+ const parent: ImageEditor = this.parent;
1997
+ const isSelection: boolean = parent.activeObj.shape && parent.activeObj.shape.indexOf('crop-') > -1;
1998
+ if (parent.toolbar && parent.toolbar.length === 0) {
1999
+ parent.notify('draw', { prop: 'select', onPropertyChange: false,
2000
+ value: { type: 'custom', startX: null, startY: null, width: null, height: null } });
2001
+ }
2002
+ parent.notify('toolbar', { prop: 'performCropTransformClick', value: {shape: null }});
2003
+ parent.setStraighten(degree);
2004
+ if (!isSelection) {
2005
+ parent.okBtn();
2006
+ }
2007
+ }
2008
+ }