@syncfusion/ej2-image-editor 29.2.5 → 30.1.37

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 (95) hide show
  1. package/.eslintrc.json +2 -0
  2. package/dist/ej2-image-editor.umd.min.js +2 -2
  3. package/dist/ej2-image-editor.umd.min.js.map +1 -1
  4. package/dist/es6/ej2-image-editor.es2015.js +883 -225
  5. package/dist/es6/ej2-image-editor.es2015.js.map +1 -1
  6. package/dist/es6/ej2-image-editor.es5.js +905 -235
  7. package/dist/es6/ej2-image-editor.es5.js.map +1 -1
  8. package/dist/global/ej2-image-editor.min.js +2 -2
  9. package/dist/global/ej2-image-editor.min.js.map +1 -1
  10. package/dist/global/index.d.ts +1 -1
  11. package/package.json +15 -47
  12. package/src/image-editor/action/crop.js +1 -1
  13. package/src/image-editor/action/draw.d.ts +1 -0
  14. package/src/image-editor/action/draw.js +103 -31
  15. package/src/image-editor/action/export.js +3 -0
  16. package/src/image-editor/action/selection.d.ts +1 -0
  17. package/src/image-editor/action/selection.js +39 -4
  18. package/src/image-editor/action/shape.d.ts +1 -0
  19. package/src/image-editor/action/shape.js +334 -49
  20. package/src/image-editor/action/transform.js +50 -43
  21. package/src/image-editor/action/undo-redo.d.ts +2 -0
  22. package/src/image-editor/action/undo-redo.js +22 -1
  23. package/src/image-editor/base/enum.d.ts +3 -1
  24. package/src/image-editor/base/enum.js +2 -0
  25. package/src/image-editor/base/image-editor.d.ts +13 -2
  26. package/src/image-editor/base/image-editor.js +242 -27
  27. package/src/image-editor/base/interface.d.ts +17 -1
  28. package/src/image-editor/renderer/toolbar.d.ts +2 -0
  29. package/src/image-editor/renderer/toolbar.js +110 -79
  30. package/styles/bds-lite.css +4 -0
  31. package/styles/bds.css +8 -0
  32. package/styles/bootstrap-dark-lite.css +4 -0
  33. package/styles/bootstrap-dark.css +4 -0
  34. package/styles/bootstrap-lite.css +4 -0
  35. package/styles/bootstrap.css +4 -0
  36. package/styles/bootstrap4-lite.css +4 -0
  37. package/styles/bootstrap4.css +4 -0
  38. package/styles/bootstrap5-dark-lite.css +4 -0
  39. package/styles/bootstrap5-dark.css +4 -0
  40. package/styles/bootstrap5-lite.css +4 -0
  41. package/styles/bootstrap5.3-lite.css +4 -0
  42. package/styles/bootstrap5.3.css +4 -0
  43. package/styles/bootstrap5.css +4 -0
  44. package/styles/fabric-dark-lite.css +4 -0
  45. package/styles/fabric-dark.css +19 -0
  46. package/styles/fabric-lite.css +4 -0
  47. package/styles/fabric.css +19 -0
  48. package/styles/fluent-dark-lite.css +4 -0
  49. package/styles/fluent-dark.css +13 -0
  50. package/styles/fluent-lite.css +4 -0
  51. package/styles/fluent.css +13 -0
  52. package/styles/fluent2-lite.css +8 -0
  53. package/styles/fluent2.css +12 -0
  54. package/styles/highcontrast-light-lite.css +4 -0
  55. package/styles/highcontrast-light.css +4 -0
  56. package/styles/highcontrast-lite.css +9 -1
  57. package/styles/highcontrast.css +14 -1
  58. package/styles/image-editor/_bigger.scss +56 -0
  59. package/styles/image-editor/_highcontrast-definition.scss +1 -1
  60. package/styles/image-editor/_layout.scss +36 -0
  61. package/styles/image-editor/bds.css +8 -0
  62. package/styles/image-editor/bootstrap-dark.css +4 -0
  63. package/styles/image-editor/bootstrap.css +4 -0
  64. package/styles/image-editor/bootstrap4.css +4 -0
  65. package/styles/image-editor/bootstrap5-dark.css +4 -0
  66. package/styles/image-editor/bootstrap5.3.css +4 -0
  67. package/styles/image-editor/bootstrap5.css +4 -0
  68. package/styles/image-editor/fabric-dark.css +19 -0
  69. package/styles/image-editor/fabric.css +19 -0
  70. package/styles/image-editor/fluent-dark.css +13 -0
  71. package/styles/image-editor/fluent.css +13 -0
  72. package/styles/image-editor/fluent2.css +12 -0
  73. package/styles/image-editor/highcontrast-light.css +4 -0
  74. package/styles/image-editor/highcontrast.css +14 -1
  75. package/styles/image-editor/material-dark.css +4 -0
  76. package/styles/image-editor/material.css +8 -0
  77. package/styles/image-editor/material3-dark.css +21 -1
  78. package/styles/image-editor/material3.css +21 -1
  79. package/styles/image-editor/tailwind-dark.css +8 -0
  80. package/styles/image-editor/tailwind.css +8 -0
  81. package/styles/image-editor/tailwind3.css +4 -0
  82. package/styles/material-dark-lite.css +4 -0
  83. package/styles/material-dark.css +4 -0
  84. package/styles/material-lite.css +4 -0
  85. package/styles/material.css +8 -0
  86. package/styles/material3-dark-lite.css +12 -0
  87. package/styles/material3-dark.css +21 -1
  88. package/styles/material3-lite.css +12 -0
  89. package/styles/material3.css +21 -1
  90. package/styles/tailwind-dark-lite.css +4 -0
  91. package/styles/tailwind-dark.css +8 -0
  92. package/styles/tailwind-lite.css +4 -0
  93. package/styles/tailwind.css +8 -0
  94. package/styles/tailwind3-lite.css +4 -0
  95. package/styles/tailwind3.css +4 -0
@@ -171,7 +171,7 @@ class Crop {
171
171
  srcTop: (actPoint.startY * ratio.height) - (img.destTop * ratio.height),
172
172
  srcWidth: (actPoint.width * ratio.width), srcHeight: (actPoint.height * ratio.height),
173
173
  destLeft: (parent.lowerCanvas.clientWidth - maxDimension.width) / 2,
174
- destTop: (parent.lowerCanvas.clientHeight - maxDimension.height + 1) / 2,
174
+ destTop: (parent.lowerCanvas.clientHeight - maxDimension.height) / 2,
175
175
  destWidth: maxDimension.width, destHeight: maxDimension.height };
176
176
  const temp = this.lowerContext.filter;
177
177
  parent.notify('draw', { prop: 'drawImage', onPropertyChange: false });
@@ -943,7 +943,7 @@ class Draw {
943
943
  this.isShapeTextInserted = false;
944
944
  this.isRotateZoom = false; // To restore zoomed image on selection crop selection
945
945
  this.tempStrokeSettings = { strokeColor: '#fff', fillColor: '', strokeWidth: null, outlineColor: '', radius: null, outlineWidth: null }; // restore stroke settings on cancel
946
- this.tempTextSettings = { text: 'Enter Text', fontFamily: '', fontSize: null, fontRatio: null, bold: false, italic: false, underline: false }; // restore text settings on cancel
946
+ this.tempTextSettings = { text: 'Enter Text', fontFamily: '', fontSize: null, fontRatio: null, bold: false, italic: false, underline: false, strikethrough: false }; // restore text settings on cancel
947
947
  this.tempAdjValue = ''; // for temp internal slider value
948
948
  this.tempFilter = ''; // restore filter style on cancel
949
949
  this.tempUndoRedoStep = 0;
@@ -1289,7 +1289,7 @@ class Draw {
1289
1289
  this.tempAdjValue = '';
1290
1290
  this.tempStrokeSettings = { strokeColor: '#fff', fillColor: '', strokeWidth: null, radius: null, outlineColor: '', outlineWidth: null };
1291
1291
  this.tempTextSettings =
1292
- { text: 'Enter Text', fontFamily: this.parent.fontFamily.default, fontSize: null, fontRatio: null, bold: false, italic: false, underline: false };
1292
+ { text: 'Enter Text', fontFamily: this.parent.fontFamily.default, fontSize: null, fontRatio: null, bold: false, italic: false, underline: false, strikethrough: false };
1293
1293
  this.tempUndoRedoStep = this.tempFreehandCounter = this.tempCurrFhdIndex = 0;
1294
1294
  this.tempZoomFactor = null;
1295
1295
  this.isCancelAction = false;
@@ -2886,7 +2886,7 @@ class Draw {
2886
2886
  const actObj = parent.activeObj;
2887
2887
  const { startX, startY, width, height } = actObj.activePoint;
2888
2888
  const rows = actObj.keyHistory.split('\n');
2889
- const { fontFamily, bold, italic } = actObj.textSettings;
2889
+ const { fontFamily, bold, italic, underline, strikethrough } = actObj.textSettings;
2890
2890
  let { fontSize } = actObj.textSettings;
2891
2891
  const lHeight = fontSize + fontSize * 0.25;
2892
2892
  const lineHeight = ((lHeight * rows.length) - (fontSize * rows.length)) / rows.length;
@@ -2900,18 +2900,18 @@ class Draw {
2900
2900
  canvasDraw.fillStyle = tempFill;
2901
2901
  for (let i = 0; i < rows.length; i++) {
2902
2902
  const text = rows[i];
2903
- const yPoint = ((i + 1) * fontSize * 0.85) + (i * lineHeight);
2903
+ const yPoint = ((i + 1) * fontSize * 0.9) + (i * lineHeight);
2904
2904
  if (parent.transform.degree === -360) {
2905
2905
  parent.transform.degree = 0;
2906
2906
  }
2907
2907
  if (parent.transform.degree === 0 || parent.transform.degree === 180) {
2908
2908
  if (fontSize > height) {
2909
- fontSize = actObj.textSettings.fontSize = height - (height * 0.1);
2909
+ fontSize = actObj.textSettings.fontSize = height / 1.18;
2910
2910
  }
2911
2911
  }
2912
2912
  else {
2913
2913
  if (fontSize > width) {
2914
- fontSize = actObj.textSettings.fontSize = width - (width * 0.1);
2914
+ fontSize = actObj.textSettings.fontSize = width / 1.18;
2915
2915
  }
2916
2916
  }
2917
2917
  canvasDraw.strokeStyle = actObj.strokeSettings.outlineColor;
@@ -2958,6 +2958,14 @@ class Draw {
2958
2958
  else {
2959
2959
  canvasDraw.strokeText(text, startX + fontSize * 0.1, startY + yPoint);
2960
2960
  canvasDraw.fillText(text, startX + fontSize * 0.1, startY + yPoint);
2961
+ if (underline) {
2962
+ const yOffset = yPoint + fontSize * 0.1;
2963
+ this.drawTextDecoration(canvasDraw, text, startX, startY, yOffset, fontSize, 0.1);
2964
+ }
2965
+ if (strikethrough) {
2966
+ const yOffset = yPoint - lineHeight - fontSize * 0.025;
2967
+ this.drawTextDecoration(canvasDraw, text, startX, startY, yOffset, fontSize, 0.1);
2968
+ }
2961
2969
  }
2962
2970
  canvasDraw.lineWidth = tempWidth;
2963
2971
  }
@@ -2967,6 +2975,18 @@ class Draw {
2967
2975
  this.drawOuterSelection(canvasDraw);
2968
2976
  }
2969
2977
  }
2978
+ drawTextDecoration(canvasDraw, text, startX, startY, yOffset, fontSize, horizontalPadding = 0.1) {
2979
+ const tempWidth = canvasDraw.lineWidth;
2980
+ const textWidth = canvasDraw.measureText(text).width;
2981
+ canvasDraw.lineWidth = fontSize * 0.1;
2982
+ canvasDraw.beginPath();
2983
+ canvasDraw.moveTo(startX + fontSize * horizontalPadding, startY + yOffset);
2984
+ canvasDraw.lineTo(startX + textWidth + fontSize * horizontalPadding, startY + yOffset);
2985
+ canvasDraw.strokeStyle = canvasDraw.fillStyle;
2986
+ canvasDraw.stroke();
2987
+ canvasDraw.lineWidth = tempWidth;
2988
+ canvasDraw.strokeStyle = this.parent.activeObj.strokeSettings.outlineColor;
2989
+ }
2970
2990
  updateActPoint(degree, canvasDraw) {
2971
2991
  const parent = this.parent;
2972
2992
  const actObj = parent.activeObj;
@@ -3213,6 +3233,14 @@ class Draw {
3213
3233
  yPoint + (i > 0 ? fontSize * 0.25 : -fontSize * 0.35));
3214
3234
  canvasDraw.fillText(text, startX + fontSize * 0.15, startY +
3215
3235
  yPoint + (i > 0 ? fontSize * 0.25 : -fontSize * 0.35));
3236
+ if (actObj.textSettings.underline) {
3237
+ const yOffset = yPoint + (i > 0 ? fontSize * 0.35 : -fontSize * 0.25);
3238
+ this.drawTextDecoration(canvasDraw, text, startX, startY, yOffset, fontSize, 0.15);
3239
+ }
3240
+ if (actObj.textSettings.strikethrough) {
3241
+ const yOffset = yPoint - lineHeight + (i > 0 ? -fontSize * 0.04 : -fontSize * 0.64);
3242
+ this.drawTextDecoration(canvasDraw, text, startX, startY, yOffset, fontSize, 0.1);
3243
+ }
3216
3244
  }
3217
3245
  }
3218
3246
  clearOuterCanvas(context) {
@@ -3262,7 +3290,7 @@ class Draw {
3262
3290
  }
3263
3291
  parent.img.destLeft = (parent.lowerCanvas.clientWidth - maxDimension.width) / 2;
3264
3292
  if (degree === 0) {
3265
- parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height + 1) / 2;
3293
+ parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height) / 2;
3266
3294
  }
3267
3295
  else {
3268
3296
  parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height) / 2;
@@ -3447,6 +3475,7 @@ class Draw {
3447
3475
  const parent = this.parent;
3448
3476
  // eslint-disable-next-line @typescript-eslint/no-this-alias
3449
3477
  const proxy = this;
3478
+ parent.imageLoaded = false;
3450
3479
  parent.baseImg.src = src;
3451
3480
  parent.baseImg.onload = () => {
3452
3481
  parent.imgSrc = src;
@@ -3491,6 +3520,10 @@ class Draw {
3491
3520
  const action = { action: 'file-open', actionEventArgs: fileOpened };
3492
3521
  parent.triggerEditCompleteEvent(action);
3493
3522
  }
3523
+ if (this.fileType === 'Bmp') {
3524
+ this.fileType = FileType.Png;
3525
+ }
3526
+ parent.imageLoaded = true;
3494
3527
  };
3495
3528
  parent.baseImg.onerror = () => {
3496
3529
  hideSpinner(parent.element);
@@ -3505,9 +3538,20 @@ class Draw {
3505
3538
  }
3506
3539
  updateBaseImgCanvas() {
3507
3540
  const parent = this.parent;
3508
- parent.baseImgCanvas.width = parent.baseImg.width;
3509
- parent.baseImgCanvas.height = parent.baseImg.height;
3510
- parent.baseImgCanvas.getContext('2d').drawImage(parent.baseImg, 0, 0);
3541
+ if (!parent.aspectRatioBaseDimension && parent.imageSettings.width && parent.imageSettings.height) {
3542
+ const widthRatio = parent.baseImg.width / parent.imageSettings.width;
3543
+ const heightRatio = parent.baseImg.height / parent.imageSettings.height;
3544
+ let ratio = (widthRatio + heightRatio) / 2;
3545
+ ratio = ratio < 1 ? 1 : ratio;
3546
+ parent.baseImgCanvas.width = parent.imageSettings.width * ratio;
3547
+ parent.baseImgCanvas.height = parent.imageSettings.height * ratio;
3548
+ parent.baseImgCanvas.getContext('2d').drawImage(parent.baseImg, 0, 0, parent.baseImgCanvas.width, parent.baseImgCanvas.height);
3549
+ }
3550
+ else {
3551
+ parent.baseImgCanvas.width = parent.baseImg.width;
3552
+ parent.baseImgCanvas.height = parent.baseImg.height;
3553
+ parent.baseImgCanvas.getContext('2d').drawImage(parent.baseImg, 0, 0);
3554
+ }
3511
3555
  }
3512
3556
  updateCanvas(isCropped, isSameDimension) {
3513
3557
  const parent = this.parent;
@@ -3534,7 +3578,7 @@ class Draw {
3534
3578
  value: { width: parent.img.srcWidth, height: parent.img.srcHeight, obj: obj, isImgShape: null } });
3535
3579
  const maxDimension = obj;
3536
3580
  parent.img.destLeft = (parent.lowerCanvas.clientWidth - maxDimension.width) / 2;
3537
- parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height + 1) / 2;
3581
+ parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height) / 2;
3538
3582
  this.drawImgToCanvas(maxDimension);
3539
3583
  this.origDim.width = parent.img.destWidth;
3540
3584
  this.origDim.height = parent.img.destHeight;
@@ -3871,7 +3915,7 @@ class Draw {
3871
3915
  }
3872
3916
  parent.notify('toolbar', { prop: 'destroy-qa-toolbar', onPropertyChange: false });
3873
3917
  this.tempTextSettings = { text: 'Enter Text', fontFamily: parent.fontFamily.default, fontSize: null, fontRatio: null, bold: false,
3874
- italic: false, underline: false };
3918
+ italic: false, underline: false, strikethrough: false };
3875
3919
  parent.objColl = extend([], this.tempObjColl, [], true);
3876
3920
  parent.pointColl = extend([], this.tempPointColl, [], true);
3877
3921
  this.renderImage();
@@ -4357,7 +4401,7 @@ class Draw {
4357
4401
  const parent = this.parent;
4358
4402
  if (parent.transform.degree % 90 === 0 && parent.transform.degree % 180 !== 0) {
4359
4403
  parent.img.destLeft = (parent.lowerCanvas.clientWidth - parent.img.destHeight) / 2;
4360
- parent.img.destTop = (parent.lowerCanvas.clientHeight - parent.img.destWidth + 1) / 2;
4404
+ parent.img.destTop = (parent.lowerCanvas.clientHeight - parent.img.destWidth) / 2;
4361
4405
  const temp = parent.img.destWidth;
4362
4406
  parent.img.destWidth = parent.img.destHeight;
4363
4407
  parent.img.destHeight = temp;
@@ -4365,7 +4409,7 @@ class Draw {
4365
4409
  else {
4366
4410
  if (isNullOrUndefined(isPreventDimension)) {
4367
4411
  parent.img.destLeft = (parent.lowerCanvas.clientWidth - parent.img.destWidth) / 2;
4368
- parent.img.destTop = (parent.lowerCanvas.clientHeight - parent.img.destHeight + 1) / 2;
4412
+ parent.img.destTop = (parent.lowerCanvas.clientHeight - parent.img.destHeight) / 2;
4369
4413
  }
4370
4414
  }
4371
4415
  }
@@ -4823,7 +4867,7 @@ class Draw {
4823
4867
  this.fileType = 'Jpeg';
4824
4868
  fileType = 'jpeg';
4825
4869
  }
4826
- if (fileType !== 'jpeg' && fileType !== 'png' && fileType !== 'svg' && fileType !== 'webp') {
4870
+ if (fileType !== 'jpeg' && fileType !== 'png' && fileType !== 'svg' && fileType !== 'webp' && fileType !== 'bmp') {
4827
4871
  this.fileType = null;
4828
4872
  }
4829
4873
  }
@@ -4856,9 +4900,9 @@ class Draw {
4856
4900
  return __awaiter(this, void 0, void 0, function* () {
4857
4901
  let response;
4858
4902
  try {
4859
- response = yield fetch(imageUrl, { method: 'HEAD' });
4860
- const contentLength = parseInt(response.headers.get('content-length') || '0', 10);
4861
- const imageSizeMB = contentLength;
4903
+ const isBlob = imageUrl.indexOf('blob:') === 0;
4904
+ response = yield fetch(imageUrl, { method: isBlob ? 'GET' : 'HEAD' });
4905
+ const imageSizeMB = isBlob ? (yield response.blob()).size : parseInt(response.headers.get('content-length') || '0', 10);
4862
4906
  callback(imageSizeMB);
4863
4907
  }
4864
4908
  catch (ex) {
@@ -5060,6 +5104,8 @@ class Draw {
5060
5104
  this.errorLoading();
5061
5105
  return;
5062
5106
  }
5107
+ parent.imageSettings = { width: null, height: null };
5108
+ parent.aspectRatioBaseDimension = null;
5063
5109
  showSpinner(parent.element);
5064
5110
  parent.element.style.opacity = '0.5';
5065
5111
  this.inputElem = inputElement;
@@ -5192,7 +5238,7 @@ class Draw {
5192
5238
  }
5193
5239
  const panX = (parent.lowerCanvas.clientWidth / 2) - (currObj.activePoint.startX +
5194
5240
  (currObj.activePoint.width / 2));
5195
- const panY = ((parent.lowerCanvas.clientHeight + 1) / 2) - (currObj.activePoint.startY +
5241
+ const panY = ((parent.lowerCanvas.clientHeight) / 2) - (currObj.activePoint.startY +
5196
5242
  (currObj.activePoint.height / 2));
5197
5243
  if (isNullOrUndefined(parent.activeObj.shape)) {
5198
5244
  parent.activeObj = extend({}, activeObj, {}, true);
@@ -5966,8 +6012,20 @@ class Draw {
5966
6012
  const point = [];
5967
6013
  const parent = this.parent;
5968
6014
  const degree = parent.transform.degree;
5969
- const width = parent.baseImg.width;
5970
- const height = parent.baseImg.height;
6015
+ let width;
6016
+ let height;
6017
+ if (!parent.aspectRatioBaseDimension && parent.imageSettings.width && parent.imageSettings.height) {
6018
+ const widthRatio = parent.baseImg.width / parent.imageSettings.width;
6019
+ const heightRatio = parent.baseImg.height / parent.imageSettings.height;
6020
+ let ratio = (widthRatio + heightRatio) / 2;
6021
+ ratio = ratio < 1 ? 1 : ratio;
6022
+ width = parent.imageSettings.width * ratio;
6023
+ height = parent.imageSettings.height * ratio;
6024
+ }
6025
+ else {
6026
+ width = parent.baseImg.width;
6027
+ height = parent.baseImg.height;
6028
+ }
5971
6029
  const obj = { dim: null, width: height, height: width, angle: parent.transform.straighten };
5972
6030
  obj['dim'] = parent.getRotatedCanvasDim(obj['width'], obj['height'], obj['angle']);
5973
6031
  const baseImgCanvasWidth = degree % 90 === 0 && degree % 180 !== 0 ? obj['dim']['width'] : parent.baseImgCanvas.width;
@@ -6239,6 +6297,9 @@ class Draw {
6239
6297
  }
6240
6298
  canvasDraw.imageSmoothingEnabled = false;
6241
6299
  canvasDraw.drawImage(offscreenCanvas, 0, 0, offscreenCanvas.width, offscreenCanvas.height, startX, startY, width, height);
6300
+ if (this.parent.imageSmoothingEnabled) {
6301
+ canvasDraw.imageSmoothingEnabled = true;
6302
+ }
6242
6303
  }
6243
6304
  obj.redactImage = this.parent.createElement('canvas');
6244
6305
  obj.redactImage.width = offscreenCanvas.width;
@@ -6292,6 +6353,9 @@ class Export {
6292
6353
  case 'drawAnnotation':
6293
6354
  this.drawAnnotation(args.value['context'], args.value['ratio']);
6294
6355
  break;
6356
+ case 'downScaleImgCanvas':
6357
+ this.downScaleImgCanvas(args.value['canvas'], args.value['width'], args.value['height']);
6358
+ break;
6295
6359
  }
6296
6360
  }
6297
6361
  getModuleName() {
@@ -8899,6 +8963,7 @@ class Selection {
8899
8963
  this.isMouseUp = false;
8900
8964
  this.mouseWheel = 0;
8901
8965
  this.isTransformedShape = false;
8966
+ this.mouseClickPoint = { x: 0, y: 0 };
8902
8967
  this.parent = parent;
8903
8968
  this.addEventListener();
8904
8969
  }
@@ -9069,7 +9134,8 @@ class Selection {
9069
9134
  parent.activeObj.textSettings.fontSize = 11;
9070
9135
  parent.activeObj.keyHistory = 'Enter Text';
9071
9136
  parent.notify('shape', { prop: 'initializeTextShape', onPropertyChange: false,
9072
- value: { text: null, fontFamily: null, fontSize: null, bold: null, italic: null, strokeColor: null } });
9137
+ value: { text: null, fontFamily: null, fontSize: null, bold: null, italic: null,
9138
+ underline: null, strikethrough: null, strokeColor: null } });
9073
9139
  }
9074
9140
  else if (args.value['shape'] === 'path') {
9075
9141
  parent.activeObj.pointColl = [];
@@ -9282,6 +9348,7 @@ class Selection {
9282
9348
  this.isSliderActive = false;
9283
9349
  this.arrowShape = [ArrowheadType.None, ArrowheadType.SolidArrow];
9284
9350
  this.isMouseDown = this.isMouseUp = this.isTransformedShape = false;
9351
+ this.mouseClickPoint = { x: 0, y: 0 };
9285
9352
  }
9286
9353
  performTabAction() {
9287
9354
  const parent = this.parent;
@@ -11315,7 +11382,7 @@ class Selection {
11315
11382
  const width = this.upperContext.measureText(parent.activeObj.textSettings.text).width +
11316
11383
  parent.activeObj.textSettings.fontSize * 0.5;
11317
11384
  actPoint.endX = actPoint.startX + width;
11318
- actPoint.endY = actPoint.startY + parent.activeObj.textSettings.fontSize;
11385
+ actPoint.endY = actPoint.startY + (parent.activeObj.textSettings.fontSize * 1.18);
11319
11386
  actPoint.width = actPoint.endX - actPoint.startX;
11320
11387
  actPoint.height = actPoint.endY - actPoint.startY;
11321
11388
  tempActiveObj = extend({}, parent.activeObj, null, true);
@@ -12118,6 +12185,7 @@ class Selection {
12118
12185
  let activePoint = parent.activeObj.activePoint;
12119
12186
  const x = imageEditorClickEventArgs.point.x;
12120
12187
  const y = imageEditorClickEventArgs.point.y;
12188
+ this.mouseClickPoint = { x: x, y: y };
12121
12189
  const cursor = parent.activeObj.shape && parent.activeObj.shape === 'text' ?
12122
12190
  parent.cursor : 'default';
12123
12191
  const tempCursor = parent.upperCanvas.style.cursor;
@@ -12168,7 +12236,7 @@ class Selection {
12168
12236
  value: { isTextBox: null } });
12169
12237
  const width = this.upperContext.measureText(parent.activeObj.textSettings.text).width + parent.activeObj.textSettings.fontSize * 0.5;
12170
12238
  activePoint.endX = activePoint.startX + width;
12171
- activePoint.endY = activePoint.startY + parent.activeObj.textSettings.fontSize;
12239
+ activePoint.endY = activePoint.startY + (parent.activeObj.textSettings.fontSize * 1.18);
12172
12240
  activePoint.width = activePoint.endX - activePoint.startX;
12173
12241
  activePoint.height = activePoint.endY - activePoint.startY;
12174
12242
  }
@@ -12597,6 +12665,12 @@ class Selection {
12597
12665
  const bbox = parent.lowerCanvas.getBoundingClientRect();
12598
12666
  x -= bbox.left;
12599
12667
  y -= bbox.top;
12668
+ if (parent.drawingShape === 'text' && this.mouseDownPoint && this.mouseDownPoint.x === x && this.mouseDownPoint.y === y) {
12669
+ parent.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false });
12670
+ if (!parent.activeObj.keyHistory) {
12671
+ parent.activeObj.keyHistory = 'Enter Text';
12672
+ }
12673
+ }
12600
12674
  let activeObjShape;
12601
12675
  const currentDrawingShape = this.currentDrawingShape;
12602
12676
  let dummyClick = false;
@@ -12774,6 +12848,12 @@ class Selection {
12774
12848
  }
12775
12849
  }
12776
12850
  if (!isCropSelection) {
12851
+ let isDummyClick = false;
12852
+ if (Math.round(x) === Math.round(this.mouseClickPoint.x) && Math.round(y) ===
12853
+ Math.round(this.mouseClickPoint.y)) {
12854
+ isDummyClick = true;
12855
+ parent.notify('undo-redo', { prop: 'preventApplyEditComplete', value: { bool: true } });
12856
+ }
12777
12857
  this.adjustActObjForLineArrow();
12778
12858
  if (parent.isShapeDrawing) {
12779
12859
  const temp = this.currentDrawingShape;
@@ -12783,6 +12863,9 @@ class Selection {
12783
12863
  else {
12784
12864
  parent.notify('undo-redo', { prop: 'updateUndoRedoStack', onPropertyChange: false });
12785
12865
  }
12866
+ if (isDummyClick) {
12867
+ parent.notify('undo-redo', { prop: 'preventApplyEditComplete', value: { bool: false } });
12868
+ }
12786
12869
  }
12787
12870
  }
12788
12871
  }
@@ -12846,6 +12929,7 @@ class Selection {
12846
12929
  parent.notify('freehand-draw', { prop: 'resetSelPoints', onPropertyChange: false });
12847
12930
  }
12848
12931
  this.isMouseUp = false;
12932
+ this.mouseClickPoint = { x: 0, y: 0 };
12849
12933
  }
12850
12934
  adjustActObjForLineArrow(obj) {
12851
12935
  let isAdjusted = false;
@@ -13127,7 +13211,8 @@ class Selection {
13127
13211
  (obj.textSettings && Math.round(obj.textSettings.fontRatio) !== Math.round(this.tempActiveObj.textSettings.fontRatio)) ||
13128
13212
  (obj.textSettings && obj.textSettings.bold !== this.tempActiveObj.textSettings.bold) ||
13129
13213
  (obj.textSettings && obj.textSettings.italic !== this.tempActiveObj.textSettings.italic) ||
13130
- (obj.textSettings && obj.textSettings.underline !== this.tempActiveObj.textSettings.underline)) {
13214
+ (obj.textSettings && obj.textSettings.underline !== this.tempActiveObj.textSettings.underline) ||
13215
+ (obj.textSettings && obj.textSettings.strikethrough !== this.tempActiveObj.textSettings.strikethrough)) {
13131
13216
  isApply = true;
13132
13217
  }
13133
13218
  if (this.isInitialTextEdited && !isApply) {
@@ -14171,6 +14256,17 @@ class Selection {
14171
14256
  else {
14172
14257
  parent.activeObj.textSettings.italic = false;
14173
14258
  }
14259
+ parent.activeObj.textSettings.underline = parent.activeObj.textSettings.strikethrough = false;
14260
+ if (parent.textArea.style.textDecoration === 'underline line-through') {
14261
+ parent.activeObj.textSettings.underline = true;
14262
+ parent.activeObj.textSettings.strikethrough = true;
14263
+ }
14264
+ else if (parent.textArea.style.textDecoration === 'underline') {
14265
+ parent.activeObj.textSettings.underline = true;
14266
+ }
14267
+ else if (parent.textArea.style.textDecoration === 'line-through') {
14268
+ parent.activeObj.textSettings.strikethrough = true;
14269
+ }
14174
14270
  parent.activeObj.textSettings.fontSize = (parseFloat(parent.textArea.style.fontSize));
14175
14271
  }
14176
14272
  rgbToHex(r, g, b, a) {
@@ -14322,6 +14418,9 @@ class Selection {
14322
14418
  if (parent.activeObj.textSettings.underline) {
14323
14419
  fontStyle.push('underline');
14324
14420
  }
14421
+ if (parent.activeObj.textSettings.strikethrough) {
14422
+ fontStyle.push('strikethrough');
14423
+ }
14325
14424
  }
14326
14425
  const { startX, startY, endX, endY, width, height } = parent.activeObj.activePoint;
14327
14426
  const { keyHistory, currIndex, shape, textSettings, strokeSettings, rotatedAngle, imageElement, opacity } = parent.activeObj;
@@ -14509,7 +14608,7 @@ class Selection {
14509
14608
  /* eslint-disable no-constant-condition */
14510
14609
  class Shape {
14511
14610
  constructor(parent) {
14512
- this.textSettings = { text: 'Enter Text', fontFamily: '', fontSize: null, fontRatio: null, bold: false, italic: false, underline: false };
14611
+ this.textSettings = { text: 'Enter Text', fontFamily: '', fontSize: null, fontRatio: null, bold: false, italic: false, underline: false, strikethrough: false };
14513
14612
  this.strokeSettings = { strokeColor: '#fff', fillColor: '', strokeWidth: null, radius: null, outlineColor: '', outlineWidth: null };
14514
14613
  this.keyHistory = ''; // text history
14515
14614
  this.preventFrameAnnotation = false;
@@ -14552,7 +14651,7 @@ class Shape {
14552
14651
  this.drawRectangle(args.value['x'], args.value['y'], args.value['width'], args.value['height'], args.value['strokeWidth'], args.value['strokeColor'], args.value['fillColor'], args.value['degree'], args.value['isSelected'], args.value['radius']);
14553
14652
  break;
14554
14653
  case 'drawText':
14555
- this.drawText(args.value['x'], args.value['y'], args.value['text'], args.value['fontFamily'], args.value['fontSize'], args.value['bold'], args.value['italic'], args.value['color'], args.value['isSelected'], args.value['degree'], args.value['fillColor'], args.value['outlineColor'], args.value['outlineWidth'], args.value['transformCollection']);
14654
+ this.drawText(args.value['x'], args.value['y'], args.value['text'], args.value['fontFamily'], args.value['fontSize'], args.value['bold'], args.value['italic'], args.value['color'], args.value['isSelected'], args.value['degree'], args.value['fillColor'], args.value['outlineColor'], args.value['outlineWidth'], args.value['transformCollection'], args.value['underline'], args.value['strikethrough']);
14556
14655
  break;
14557
14656
  case 'redrawActObj':
14558
14657
  this.redrawActObj(args.value['x'], args.value['y'], args.value['isMouseDown']);
@@ -14716,7 +14815,7 @@ class Shape {
14716
14815
  this.alignTextAreaIntoCanvas();
14717
14816
  break;
14718
14817
  case 'initializeTextShape':
14719
- this.initializeTextShape(args.value['text'], args.value['fontFamily'], args.value['fontSize'], args.value['bold'], args.value['italic'], args.value['strokeColor'], args.value['fillColor'], args.value['outlineColor'], args.value['outlineWidth']);
14818
+ this.initializeTextShape(args.value['text'], args.value['fontFamily'], args.value['fontSize'], args.value['bold'], args.value['italic'], args.value['underline'], args.value['strikethrough'], args.value['strokeColor'], args.value['fillColor'], args.value['outlineColor'], args.value['outlineWidth']);
14720
14819
  break;
14721
14820
  case 'stopPathDrawing':
14722
14821
  this.stopPathDrawing(args.value['e'], args.value['isApply']);
@@ -14811,7 +14910,7 @@ class Shape {
14811
14910
  }
14812
14911
  reset() {
14813
14912
  this.textSettings =
14814
- { text: 'Enter Text', fontFamily: this.parent.fontFamily.default, fontSize: null, fontRatio: null, bold: false, italic: false, underline: false };
14913
+ { text: 'Enter Text', fontFamily: this.parent.fontFamily.default, fontSize: null, fontRatio: null, bold: false, italic: false, underline: false, strikethrough: false };
14815
14914
  this.strokeSettings = { strokeColor: '#fff', fillColor: '', strokeWidth: null, radius: null, outlineColor: '', outlineWidth: null };
14816
14915
  this.preventFrameAnnotation = false;
14817
14916
  }
@@ -14851,8 +14950,8 @@ class Shape {
14851
14950
  const start = x && y ? { x: x, y: y } : null;
14852
14951
  this.drawShape('redact', null, null, null, start, width, height, null, null, null, null, null, null, null, type, value);
14853
14952
  }
14854
- drawText(x, y, text, fontFamily, fontSize, bold, italic, color, isSelected, degree, fillColor, outlineColor, outlineWidth, transformCollection) {
14855
- this.drawShapeText(text, fontFamily, fontSize, bold, italic, color, x, y, isSelected, degree, fillColor, outlineColor, outlineWidth, transformCollection);
14953
+ drawText(x, y, text, fontFamily, fontSize, bold, italic, color, isSelected, degree, fillColor, outlineColor, outlineWidth, transformCollection, underline, strikethrough) {
14954
+ this.drawShapeText(text, fontFamily, fontSize, bold, italic, color, x, y, isSelected, degree, fillColor, outlineColor, outlineWidth, transformCollection, underline, strikethrough);
14856
14955
  }
14857
14956
  initializeShape(type) {
14858
14957
  const parent = this.parent;
@@ -15038,7 +15137,7 @@ class Shape {
15038
15137
  value: { obj: selPointCollObj } });
15039
15138
  this.prevObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true);
15040
15139
  }
15041
- drawShapeText(text, fontFamily, fontSize, bold, italic, strokeColor, x, y, isSelected, degree, fillColor, outlineColor, outlineWidth, transformCollection) {
15140
+ drawShapeText(text, fontFamily, fontSize, bold, italic, strokeColor, x, y, isSelected, degree, fillColor, outlineColor, outlineWidth, transformCollection, underline, strikethrough) {
15042
15141
  const parent = this.parent;
15043
15142
  if (!parent.disabled && parent.isImageLoaded) {
15044
15143
  if (parent.currObjType.shape === 'freehanddraw') {
@@ -15053,7 +15152,7 @@ class Shape {
15053
15152
  this.refreshActiveObj();
15054
15153
  parent.activeObj.shape = parent.currObjType.shape = 'text';
15055
15154
  parent.currObjType.isCustomCrop = false;
15056
- this.initializeTextShape(text, fontFamily, fontSize, bold, italic, strokeColor, fillColor, outlineColor, outlineWidth);
15155
+ this.initializeTextShape(text, fontFamily, fontSize, bold, italic, underline, strikethrough, strokeColor, fillColor, outlineColor, outlineWidth);
15057
15156
  parent.currObjType.isText = parent.currObjType.isInitialText = true;
15058
15157
  if (isNullOrUndefined(parent.activeObj.textSettings.fontSize)) {
15059
15158
  parent.getFontSizes();
@@ -15204,7 +15303,7 @@ class Shape {
15204
15303
  isApplyBtn: null, isCropping: null, isZooming: null, cType: null } });
15205
15304
  parent.notify('toolbar', { prop: 'update-toolbar-items', onPropertyChange: false });
15206
15305
  }
15207
- initializeTextShape(text, fontFamily, fontSize, bold, italic, strokeColor, fillColor, outlineColor, outlineWidth) {
15306
+ initializeTextShape(text, fontFamily, fontSize, bold, italic, underline, strikethrough, strokeColor, fillColor, outlineColor, outlineWidth) {
15208
15307
  const parent = this.parent;
15209
15308
  this.keyHistory = '';
15210
15309
  parent.upperCanvas.style.display = 'block';
@@ -15215,6 +15314,8 @@ class Shape {
15215
15314
  parent.activeObj.textSettings.fontSize = fontSize || parent.activeObj.textSettings.fontSize;
15216
15315
  parent.activeObj.textSettings.bold = bold || parent.activeObj.textSettings.bold;
15217
15316
  parent.activeObj.textSettings.italic = italic || parent.activeObj.textSettings.italic;
15317
+ parent.activeObj.textSettings.underline = underline || parent.activeObj.textSettings.underline;
15318
+ parent.activeObj.textSettings.strikethrough = strikethrough || parent.activeObj.textSettings.strikethrough;
15218
15319
  parent.activeObj.strokeSettings.outlineColor = outlineColor || parent.activeObj.strokeSettings.outlineColor;
15219
15320
  parent.activeObj.strokeSettings.outlineWidth = outlineWidth || parent.activeObj.strokeSettings.outlineWidth;
15220
15321
  }
@@ -15419,6 +15520,7 @@ class Shape {
15419
15520
  parent.activeObj.textSettings.bold = false;
15420
15521
  parent.activeObj.textSettings.italic = false;
15421
15522
  parent.activeObj.textSettings.underline = false;
15523
+ parent.activeObj.textSettings.strikethrough = false;
15422
15524
  for (let i = 0; i < shapeSettings.fontStyle.length; i++) {
15423
15525
  switch (shapeSettings.fontStyle[i]) {
15424
15526
  case 'bold':
@@ -15427,6 +15529,12 @@ class Shape {
15427
15529
  case 'italic':
15428
15530
  parent.activeObj.textSettings.italic = true;
15429
15531
  break;
15532
+ case 'underline':
15533
+ parent.activeObj.textSettings.underline = true;
15534
+ break;
15535
+ case 'strikethrough':
15536
+ parent.activeObj.textSettings.strikethrough = true;
15537
+ break;
15430
15538
  }
15431
15539
  }
15432
15540
  }
@@ -15445,7 +15553,7 @@ class Shape {
15445
15553
  this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
15446
15554
  this.updateFontStyles();
15447
15555
  const width = this.upperContext.measureText(this.keyHistory).width + fontSize * 0.5;
15448
- const height = fontSize;
15556
+ const height = fontSize * 1.18;
15449
15557
  this.upperContext.fillText(this.keyHistory, parent.activeObj.activePoint.startX, parent.activeObj.activePoint.startY + fontSize);
15450
15558
  this.upperContext.clearRect(0, 0, parent.upperCanvas.width, parent.upperCanvas.height);
15451
15559
  parent.currObjType.isText = true;
@@ -15468,7 +15576,7 @@ class Shape {
15468
15576
  const text = (parent.textArea.style.display === 'block' || parent.textArea.style.display === 'inline-block') ?
15469
15577
  this.getMaxText(true) : this.getMaxText();
15470
15578
  const width = this.upperContext.measureText(text).width + fontSize * 0.5;
15471
- let height = rows.length * fontSize;
15579
+ let height = rows.length * fontSize * 1.18;
15472
15580
  if (rows.length > 1) {
15473
15581
  height += (fontSize * 0.50);
15474
15582
  }
@@ -15503,7 +15611,7 @@ class Shape {
15503
15611
  parent.textArea.value = '';
15504
15612
  this.updateFontStyles();
15505
15613
  let width = this.upperContext.measureText(parent.activeObj.keyHistory).width + fontSize * 0.5;
15506
- let height = fontSize;
15614
+ let height = fontSize * 1.18;
15507
15615
  const rows = parent.activeObj.keyHistory.split('\n');
15508
15616
  if (rows.length > 1) {
15509
15617
  height *= rows.length;
@@ -16258,6 +16366,9 @@ class Shape {
16258
16366
  }
16259
16367
  parent.textArea.style.fontWeight = actObj.textSettings.bold ? 'bold' : 'normal';
16260
16368
  parent.textArea.style.fontStyle = actObj.textSettings.italic ? 'italic' : 'normal';
16369
+ parent.textArea.style.textDecoration = (actObj.textSettings.underline && actObj.textSettings.strikethrough) ? 'underline line-through' :
16370
+ (actObj.textSettings.underline) ? 'underline' :
16371
+ (actObj.textSettings.strikethrough) ? 'line-through' : 'none';
16261
16372
  parent.textArea.style.border = '2px solid ' + parent.themeColl[parent.theme]['primaryColor'];
16262
16373
  parent.textArea.value = actObj.keyHistory;
16263
16374
  parent.textArea.style.overflow = 'hidden';
@@ -16804,7 +16915,7 @@ class Shape {
16804
16915
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
16805
16916
  const fileData = filesData;
16806
16917
  const fileExtension = fileData.name && fileData.name.split('.').pop().toLowerCase();
16807
- if (fileExtension && ['jpg', 'jpeg', 'png', 'svg', 'webp'].indexOf(fileExtension) === -1) {
16918
+ if (fileExtension && ['jpg', 'jpeg', 'png', 'svg', 'webp', 'bmp'].indexOf(fileExtension) === -1) {
16808
16919
  this.refreshActiveObj();
16809
16920
  return;
16810
16921
  }
@@ -17151,9 +17262,16 @@ class Shape {
17151
17262
  const obj = { shapeSettingsObj: {} };
17152
17263
  parent.notify('selection', { prop: 'updatePrevShapeSettings', onPropertyChange: false, value: { obj: obj } });
17153
17264
  const shapeSettings = obj['shapeSettingsObj'];
17265
+ let isObjPushed = false;
17266
+ const collLength = parent.objColl.length;
17154
17267
  this.pushActItemIntoObj();
17268
+ if (collLength !== parent.objColl.length) {
17269
+ isObjPushed = true;
17270
+ }
17155
17271
  const objColl = extend([], parent.objColl, [], true);
17156
- parent.objColl.pop();
17272
+ if (isObjPushed) {
17273
+ parent.objColl.pop();
17274
+ }
17157
17275
  if (parent.textArea.style.display === 'none') {
17158
17276
  this.updateFontRatio(parent.activeObj);
17159
17277
  }
@@ -17162,24 +17280,77 @@ class Shape {
17162
17280
  }
17163
17281
  switch (item) {
17164
17282
  case 'default':
17165
- this.updateFontStyle(item, objColl, 'normal', 'normal');
17283
+ this.updateFontStyle(item, objColl, 'normal', 'normal', false, false);
17166
17284
  break;
17167
17285
  case 'bold':
17168
- this.updateFontStyle(item, objColl, 'bold', 'normal');
17286
+ this.updateFontStyle(item, objColl, 'bold', 'normal', false, false);
17169
17287
  break;
17170
17288
  case 'italic':
17171
- this.updateFontStyle(item, objColl, 'normal', 'italic');
17289
+ this.updateFontStyle(item, objColl, 'normal', 'italic', false, false);
17172
17290
  break;
17173
17291
  case 'bolditalic':
17174
- this.updateFontStyle(item, objColl, 'bold', 'italic');
17292
+ this.updateFontStyle(item, objColl, 'bold', 'italic', false, false);
17293
+ break;
17294
+ case 'underline':
17295
+ this.updateFontStyle(item, objColl, 'normal', 'normal', true, false);
17296
+ break;
17297
+ case 'boldunderline':
17298
+ this.updateFontStyle(item, objColl, 'bold', 'normal', true, false);
17299
+ break;
17300
+ case 'italicunderline':
17301
+ this.updateFontStyle(item, objColl, 'normal', 'italic', true, false);
17302
+ break;
17303
+ case 'bolditalicunderline':
17304
+ this.updateFontStyle(item, objColl, 'bold', 'italic', true, false);
17305
+ break;
17306
+ case 'strikethrough':
17307
+ this.updateFontStyle(item, objColl, 'normal', 'normal', false, true);
17308
+ break;
17309
+ case 'boldstrikethrough':
17310
+ this.updateFontStyle(item, objColl, 'bold', 'normal', false, true);
17311
+ break;
17312
+ case 'italicstrikethrough':
17313
+ this.updateFontStyle(item, objColl, 'normal', 'italic', false, true);
17314
+ break;
17315
+ case 'underlinestrikethrough':
17316
+ this.updateFontStyle(item, objColl, 'normal', 'normal', true, true);
17317
+ break;
17318
+ case 'bolditalicstrikethrough':
17319
+ this.updateFontStyle(item, objColl, 'bold', 'italic', false, true);
17320
+ break;
17321
+ case 'boldunderlinestrikethrough':
17322
+ this.updateFontStyle(item, objColl, 'bold', 'normal', true, true);
17323
+ break;
17324
+ case 'italicunderlinestrikethrough':
17325
+ this.updateFontStyle(item, objColl, 'normal', 'italic', true, true);
17326
+ break;
17327
+ case 'bolditalicunderlinestrikethrough':
17328
+ this.updateFontStyle(item, objColl, 'bold', 'italic', true, true);
17175
17329
  break;
17176
17330
  }
17177
17331
  const shapeChangedArgs = { action: 'font-style', currentShapeSettings: extend({}, shapeSettings, {}, true) };
17178
- shapeChangedArgs.currentShapeSettings.fontStyle = [item];
17332
+ shapeChangedArgs.currentShapeSettings.fontStyle = this.getFontStyleArray(item);
17179
17333
  parent.trigger('shapeChange', shapeChangedArgs);
17180
17334
  parent.editCompleteArgs = shapeChangedArgs;
17181
17335
  }
17182
- updateFontStyle(item, objColl, fontWeight, fontStyle) {
17336
+ getFontStyleArray(item) {
17337
+ const styleArray = [];
17338
+ const lowerItem = item.toLowerCase();
17339
+ if (lowerItem.indexOf('bold') > -1) {
17340
+ styleArray.push('bold');
17341
+ }
17342
+ if (lowerItem.indexOf('italic') > -1) {
17343
+ styleArray.push('italic');
17344
+ }
17345
+ if (lowerItem.indexOf('underline') > -1) {
17346
+ styleArray.push('underline');
17347
+ }
17348
+ if (lowerItem.indexOf('strikethrough') > -1) {
17349
+ styleArray.push('strikethrough');
17350
+ }
17351
+ return styleArray;
17352
+ }
17353
+ updateFontStyle(item, objColl, fontWeight, fontStyle, underline, strikethrough) {
17183
17354
  const parent = this.parent;
17184
17355
  const style = parent.textArea.style;
17185
17356
  if (style.display === 'block' || style.display === 'inline-block') {
@@ -17195,9 +17366,43 @@ class Shape {
17195
17366
  else {
17196
17367
  style.fontStyle = 'normal';
17197
17368
  }
17198
- const value = (style.fontWeight === 'normal' && style.fontStyle === 'normal' ? 'default' :
17199
- (style.fontWeight === 'bold' && style.fontStyle === 'normal' ? 'bold' :
17200
- (style.fontWeight === 'normal' && style.fontStyle === 'italic' ? 'italic' : 'bolditalic')));
17369
+ if (underline && strikethrough) {
17370
+ style.textDecoration = 'underline line-through';
17371
+ }
17372
+ else if (strikethrough) {
17373
+ style.textDecoration = 'line-through';
17374
+ }
17375
+ else if (underline) {
17376
+ style.textDecoration = 'underline';
17377
+ }
17378
+ else {
17379
+ style.textDecoration = 'none';
17380
+ }
17381
+ const key = [
17382
+ style.fontWeight === 'bold' ? 'bold' : '',
17383
+ style.fontStyle === 'italic' ? 'italic' : '',
17384
+ typeof style.textDecoration === 'string' && style.textDecoration.indexOf('underline') > -1 ? 'underline' : '',
17385
+ typeof style.textDecoration === 'string' && style.textDecoration.indexOf('line-through') > -1 ? 'strikethrough' : ''
17386
+ ].filter(Boolean).join('');
17387
+ const valueMap = {
17388
+ '': 'default',
17389
+ bold: 'bold',
17390
+ italic: 'italic',
17391
+ underline: 'underline',
17392
+ strikethrough: 'strikethrough',
17393
+ bolditalic: 'bolditalic',
17394
+ boldunderline: 'boldunderline',
17395
+ boldstrikethrough: 'boldstrikethrough',
17396
+ italicunderline: 'italicunderline',
17397
+ italicstrikethrough: 'italicstrikethrough',
17398
+ underlinestrikethrough: 'underlinestrikethrough',
17399
+ bolditalicunderline: 'bolditalicunderline',
17400
+ bolditalicstrikethrough: 'bolditalicstrikethrough',
17401
+ boldunderlinestrikethrough: 'boldunderlinestrikethrough',
17402
+ italicunderlinestrikethrough: 'italicunderlinestrikethrough',
17403
+ bolditalicunderlinestrikethrough: 'bolditalicunderlinestrikethrough'
17404
+ };
17405
+ const value = key in valueMap ? valueMap[key] : 'default';
17201
17406
  const width = this.getTextAreaWidth(value);
17202
17407
  style.width = width + 'px';
17203
17408
  this.updateObjColl(item, objColl);
@@ -17205,6 +17410,8 @@ class Shape {
17205
17410
  else {
17206
17411
  this.textSettings.bold = parent.activeObj.textSettings.bold = fontWeight === 'normal' ? false : true;
17207
17412
  this.textSettings.italic = parent.activeObj.textSettings.italic = fontStyle === 'normal' ? false : true;
17413
+ this.textSettings.underline = parent.activeObj.textSettings.underline = underline ? true : false;
17414
+ this.textSettings.strikethrough = parent.activeObj.textSettings.strikethrough = strikethrough ? true : false;
17208
17415
  if (parent.activeObj.activePoint.width !== 0 || parent.activeObj.activePoint.height !== 0) {
17209
17416
  this.redrawText();
17210
17417
  }
@@ -17298,24 +17505,107 @@ class Shape {
17298
17505
  parent.notify('freehand-draw', { prop: 'getSelPointColl', onPropertyChange: false,
17299
17506
  value: { obj: selPointCollObj } });
17300
17507
  prevObj.selPointColl = extend([], selPointCollObj['selPointColl'], [], true);
17301
- const tempBold = parent.activeObj.textSettings.bold;
17302
- const tempItalic = parent.activeObj.textSettings.italic;
17508
+ const textSettings = parent.activeObj.textSettings;
17509
+ const tempBold = textSettings.bold;
17510
+ const tempItalic = textSettings.italic;
17511
+ const tempUnderline = textSettings.underline;
17512
+ const tempStrikethrough = textSettings.strikethrough;
17303
17513
  switch (item) {
17304
17514
  case 'default':
17305
- parent.activeObj.textSettings.bold = false;
17306
- parent.activeObj.textSettings.italic = false;
17515
+ textSettings.bold = false;
17516
+ textSettings.italic = false;
17517
+ textSettings.underline = false;
17518
+ textSettings.strikethrough = false;
17307
17519
  break;
17308
17520
  case 'bold':
17309
- parent.activeObj.textSettings.bold = true;
17310
- parent.activeObj.textSettings.italic = false;
17521
+ textSettings.bold = true;
17522
+ textSettings.italic = false;
17523
+ textSettings.underline = false;
17524
+ textSettings.strikethrough = false;
17311
17525
  break;
17312
17526
  case 'italic':
17313
- parent.activeObj.textSettings.bold = false;
17314
- parent.activeObj.textSettings.italic = true;
17527
+ textSettings.bold = false;
17528
+ textSettings.italic = true;
17529
+ textSettings.underline = false;
17530
+ textSettings.strikethrough = false;
17315
17531
  break;
17316
17532
  case 'bolditalic':
17317
- parent.activeObj.textSettings.bold = true;
17318
- parent.activeObj.textSettings.italic = true;
17533
+ textSettings.bold = true;
17534
+ textSettings.italic = true;
17535
+ textSettings.underline = false;
17536
+ textSettings.strikethrough = false;
17537
+ break;
17538
+ case 'underline':
17539
+ textSettings.bold = false;
17540
+ textSettings.italic = false;
17541
+ textSettings.underline = true;
17542
+ textSettings.strikethrough = false;
17543
+ break;
17544
+ case 'boldunderline':
17545
+ textSettings.bold = true;
17546
+ textSettings.italic = false;
17547
+ textSettings.underline = true;
17548
+ textSettings.strikethrough = false;
17549
+ break;
17550
+ case 'italicunderline':
17551
+ textSettings.bold = false;
17552
+ textSettings.italic = true;
17553
+ textSettings.underline = true;
17554
+ textSettings.strikethrough = false;
17555
+ break;
17556
+ case 'bolditalicunderline':
17557
+ textSettings.bold = true;
17558
+ textSettings.italic = true;
17559
+ textSettings.underline = true;
17560
+ textSettings.strikethrough = false;
17561
+ break;
17562
+ case 'strikethrough':
17563
+ textSettings.bold = false;
17564
+ textSettings.italic = false;
17565
+ textSettings.underline = false;
17566
+ textSettings.strikethrough = true;
17567
+ break;
17568
+ case 'boldstrikethrough':
17569
+ textSettings.bold = true;
17570
+ textSettings.italic = false;
17571
+ textSettings.underline = false;
17572
+ textSettings.strikethrough = true;
17573
+ break;
17574
+ case 'italicstrikethrough':
17575
+ textSettings.bold = false;
17576
+ textSettings.italic = true;
17577
+ textSettings.underline = false;
17578
+ textSettings.strikethrough = true;
17579
+ break;
17580
+ case 'underlinestrikethrough':
17581
+ textSettings.bold = false;
17582
+ textSettings.italic = false;
17583
+ textSettings.underline = true;
17584
+ textSettings.strikethrough = true;
17585
+ break;
17586
+ case 'bolditalicstrikethrough':
17587
+ textSettings.bold = true;
17588
+ textSettings.italic = true;
17589
+ textSettings.underline = false;
17590
+ textSettings.strikethrough = true;
17591
+ break;
17592
+ case 'boldunderlinestrikethrough':
17593
+ textSettings.bold = true;
17594
+ textSettings.italic = false;
17595
+ textSettings.underline = true;
17596
+ textSettings.strikethrough = true;
17597
+ break;
17598
+ case 'italicunderlinestrikethrough':
17599
+ textSettings.bold = false;
17600
+ textSettings.italic = true;
17601
+ textSettings.underline = true;
17602
+ textSettings.strikethrough = true;
17603
+ break;
17604
+ case 'bolditalicunderlinestrikethrough':
17605
+ textSettings.bold = true;
17606
+ textSettings.italic = true;
17607
+ textSettings.underline = true;
17608
+ textSettings.strikethrough = true;
17319
17609
  break;
17320
17610
  }
17321
17611
  parent.objColl.push(parent.activeObj);
@@ -17325,8 +17615,10 @@ class Shape {
17325
17615
  previousCropObj: prevCropObj, previousText: null,
17326
17616
  currentText: null, previousFilter: null, isCircleCrop: null } });
17327
17617
  parent.objColl.pop();
17328
- parent.activeObj.textSettings.bold = tempBold;
17329
- parent.activeObj.textSettings.italic = tempItalic;
17618
+ textSettings.bold = tempBold;
17619
+ textSettings.italic = tempItalic;
17620
+ textSettings.underline = tempUnderline;
17621
+ textSettings.strikethrough = tempStrikethrough;
17330
17622
  }
17331
17623
  pushActItemIntoObj() {
17332
17624
  const parent = this.parent;
@@ -17519,24 +17811,107 @@ class Shape {
17519
17811
  }
17520
17812
  getTextAreaWidth(item) {
17521
17813
  const parent = this.parent;
17522
- const tempBold = parent.activeObj.textSettings.bold;
17523
- const tempItalic = parent.activeObj.textSettings.italic;
17814
+ const textSettings = parent.activeObj.textSettings;
17815
+ const tempBold = textSettings.bold;
17816
+ const tempItalic = textSettings.italic;
17817
+ const tempUnderline = textSettings.underline;
17818
+ const tempStrikethrough = textSettings.strikethrough;
17524
17819
  switch (item) {
17525
17820
  case 'default':
17526
- parent.activeObj.textSettings.bold = false;
17527
- parent.activeObj.textSettings.italic = false;
17821
+ textSettings.bold = false;
17822
+ textSettings.italic = false;
17823
+ textSettings.underline = false;
17824
+ textSettings.strikethrough = false;
17528
17825
  break;
17529
17826
  case 'bold':
17530
- parent.activeObj.textSettings.bold = true;
17531
- parent.activeObj.textSettings.italic = false;
17827
+ textSettings.bold = true;
17828
+ textSettings.italic = false;
17829
+ textSettings.underline = false;
17830
+ textSettings.strikethrough = false;
17532
17831
  break;
17533
17832
  case 'italic':
17534
- parent.activeObj.textSettings.bold = false;
17535
- parent.activeObj.textSettings.italic = true;
17833
+ textSettings.bold = false;
17834
+ textSettings.italic = true;
17835
+ textSettings.underline = false;
17836
+ textSettings.strikethrough = false;
17536
17837
  break;
17537
17838
  case 'bolditalic':
17538
- parent.activeObj.textSettings.bold = true;
17539
- parent.activeObj.textSettings.italic = true;
17839
+ textSettings.bold = true;
17840
+ textSettings.italic = true;
17841
+ textSettings.underline = false;
17842
+ textSettings.strikethrough = false;
17843
+ break;
17844
+ case 'underline':
17845
+ textSettings.bold = false;
17846
+ textSettings.italic = false;
17847
+ textSettings.underline = true;
17848
+ textSettings.strikethrough = false;
17849
+ break;
17850
+ case 'boldunderline':
17851
+ textSettings.bold = true;
17852
+ textSettings.italic = false;
17853
+ textSettings.underline = true;
17854
+ textSettings.strikethrough = false;
17855
+ break;
17856
+ case 'italicunderline':
17857
+ textSettings.bold = false;
17858
+ textSettings.italic = true;
17859
+ textSettings.underline = true;
17860
+ textSettings.strikethrough = false;
17861
+ break;
17862
+ case 'bolditalicunderline':
17863
+ textSettings.bold = true;
17864
+ textSettings.italic = true;
17865
+ textSettings.underline = true;
17866
+ textSettings.strikethrough = false;
17867
+ break;
17868
+ case 'strikethrough':
17869
+ textSettings.bold = false;
17870
+ textSettings.italic = false;
17871
+ textSettings.underline = false;
17872
+ textSettings.strikethrough = true;
17873
+ break;
17874
+ case 'boldstrikethrough':
17875
+ textSettings.bold = true;
17876
+ textSettings.italic = false;
17877
+ textSettings.underline = false;
17878
+ textSettings.strikethrough = true;
17879
+ break;
17880
+ case 'italicstrikethrough':
17881
+ textSettings.bold = false;
17882
+ textSettings.italic = true;
17883
+ textSettings.underline = false;
17884
+ textSettings.strikethrough = true;
17885
+ break;
17886
+ case 'underlinestrikethrough':
17887
+ textSettings.bold = false;
17888
+ textSettings.italic = false;
17889
+ textSettings.underline = true;
17890
+ textSettings.strikethrough = true;
17891
+ break;
17892
+ case 'bolditalicstrikethrough':
17893
+ textSettings.bold = true;
17894
+ textSettings.italic = true;
17895
+ textSettings.underline = false;
17896
+ textSettings.strikethrough = true;
17897
+ break;
17898
+ case 'boldunderlinestrikethrough':
17899
+ textSettings.bold = true;
17900
+ textSettings.italic = false;
17901
+ textSettings.underline = true;
17902
+ textSettings.strikethrough = true;
17903
+ break;
17904
+ case 'italicunderlinestrikethrough':
17905
+ textSettings.bold = false;
17906
+ textSettings.italic = true;
17907
+ textSettings.underline = true;
17908
+ textSettings.strikethrough = true;
17909
+ break;
17910
+ case 'bolditalicunderlinestrikethrough':
17911
+ textSettings.bold = true;
17912
+ textSettings.italic = true;
17913
+ textSettings.underline = true;
17914
+ textSettings.strikethrough = true;
17540
17915
  break;
17541
17916
  }
17542
17917
  const isTextArea = parent.textArea.style.display === 'none' ? false : true;
@@ -17544,14 +17919,16 @@ class Shape {
17544
17919
  let width;
17545
17920
  if (!isTextArea) {
17546
17921
  width = this.upperContext.measureText(parent.activeObj.keyHistory).width +
17547
- parent.activeObj.textSettings.fontSize * 0.5;
17922
+ textSettings.fontSize * 0.5;
17548
17923
  }
17549
17924
  else {
17550
17925
  width = this.upperContext.measureText(parent.textArea.value).width +
17551
- parent.activeObj.textSettings.fontSize * 0.5;
17926
+ textSettings.fontSize * 0.5;
17552
17927
  }
17553
- parent.activeObj.textSettings.bold = tempBold;
17554
- parent.activeObj.textSettings.italic = tempItalic;
17928
+ textSettings.bold = tempBold;
17929
+ textSettings.italic = tempItalic;
17930
+ textSettings.underline = tempUnderline;
17931
+ textSettings.strikethrough = tempStrikethrough;
17555
17932
  return width;
17556
17933
  }
17557
17934
  getRedactObjDetails(obj) {
@@ -17630,6 +18007,12 @@ class Shape {
17630
18007
  if (obj.textSettings.italic) {
17631
18008
  shapeDetails.fontStyle.push('italic');
17632
18009
  }
18010
+ if (obj.textSettings.underline) {
18011
+ shapeDetails.fontStyle.push('underline');
18012
+ }
18013
+ if (obj.textSettings.strikethrough) {
18014
+ shapeDetails.fontStyle.push('strikethrough');
18015
+ }
17633
18016
  shapeDetails.degree = obj.rotatedAngle * (180 / Math.PI);
17634
18017
  parent.notify('selection', { prop: 'updateTransColl', onPropertyChange: false, value: { obj: transformObj, object: obj } });
17635
18018
  shapeDetails.transformCollection = transformObj['coll'];
@@ -17929,6 +18312,7 @@ class Shape {
17929
18312
  this.lowerContext.clearRect(0, 0, parent.lowerCanvas.width, parent.lowerCanvas.height);
17930
18313
  parent.notify('draw', { prop: 'redrawImgWithObj', onPropertyChange: false });
17931
18314
  parent.notify('toolbar', { prop: 'refresh-main-toolbar', onPropertyChange: false });
18315
+ parent.notify('undo-redo', { prop: 'updateCurrUrc', value: { type: 'ok' } });
17932
18316
  }
17933
18317
  }
17934
18318
  getMaxText(isTextBox, text, obj) {
@@ -19344,40 +19728,40 @@ class Transform {
19344
19728
  destWidth: parent.img.destWidth, destHeight: parent.img.destHeight };
19345
19729
  if (parent.activeObj.shape) {
19346
19730
  const maxDimension = this.setZoomDimension(-0.1, parent.activeObj);
19347
- if (!isNullOrUndefined(zoomOut)) {
19348
- const actPoint = parent.activeObj.activePoint;
19349
- if (parent.transform.straighten === 0) {
19350
- if (parent.img.destLeft > actPoint.startX || parent.img.destTop >
19351
- actPoint.startY || parent.img.destLeft + parent.img.destWidth <
19352
- actPoint.endX || parent.img.destTop + parent.img.destHeight < actPoint.endY
19353
- || zoomFactor === minZoomFactor) {
19354
- zoomOut.classList.add('e-disabled');
19355
- zoomOut.parentElement.classList.add('e-overlay');
19356
- isDisabled = true;
19357
- }
19358
- else {
19359
- zoomOut.classList.remove('e-disabled');
19360
- zoomOut.parentElement.classList.remove('e-overlay');
19361
- isDisabled = false;
19362
- }
19731
+ const actPoint = parent.activeObj.activePoint;
19732
+ if (parent.transform.straighten === 0) {
19733
+ if (parent.img.destLeft > actPoint.startX || parent.img.destTop >
19734
+ actPoint.startY || parent.img.destLeft + parent.img.destWidth <
19735
+ actPoint.endX || parent.img.destTop + parent.img.destHeight < actPoint.endY
19736
+ || zoomFactor === minZoomFactor) {
19737
+ isDisabled = true;
19363
19738
  }
19364
19739
  else {
19365
- parent.img.destWidth = maxDimension.width;
19366
- parent.img.destHeight = maxDimension.height;
19367
- const obj = { isIntersect: null };
19368
- parent.notify('draw', { prop: 'updateImgCanvasPoints', onPropertyChange: false });
19369
- parent.notify('draw', { prop: 'isLinesIntersect', onPropertyChange: false, value: { obj: obj } });
19370
- if (obj['isIntersect'] ||
19371
- zoomFactor === minZoomFactor) {
19372
- zoomOut.classList.add('e-disabled');
19373
- zoomOut.parentElement.classList.add('e-overlay');
19374
- isDisabled = true;
19375
- }
19376
- else {
19377
- zoomOut.classList.remove('e-disabled');
19378
- zoomOut.parentElement.classList.remove('e-overlay');
19379
- isDisabled = false;
19380
- }
19740
+ isDisabled = false;
19741
+ }
19742
+ }
19743
+ else {
19744
+ parent.img.destWidth = maxDimension.width;
19745
+ parent.img.destHeight = maxDimension.height;
19746
+ const obj = { isIntersect: null };
19747
+ parent.notify('draw', { prop: 'updateImgCanvasPoints', onPropertyChange: false });
19748
+ parent.notify('draw', { prop: 'isLinesIntersect', onPropertyChange: false, value: { obj: obj } });
19749
+ if (obj['isIntersect'] ||
19750
+ zoomFactor === minZoomFactor) {
19751
+ isDisabled = true;
19752
+ }
19753
+ else {
19754
+ isDisabled = false;
19755
+ }
19756
+ }
19757
+ if (zoomOut) {
19758
+ if (isDisabled) {
19759
+ zoomOut.classList.add('e-disabled');
19760
+ zoomOut.parentElement.classList.add('e-overlay');
19761
+ }
19762
+ else {
19763
+ zoomOut.classList.remove('e-disabled');
19764
+ zoomOut.parentElement.classList.remove('e-overlay');
19381
19765
  }
19382
19766
  }
19383
19767
  }
@@ -19413,7 +19797,7 @@ class Transform {
19413
19797
  maxDimension.width += (maxDimension.width * parent.transform.zoomFactor);
19414
19798
  maxDimension.height += (maxDimension.height * parent.transform.zoomFactor);
19415
19799
  parent.img.destLeft = (parent.lowerCanvas.clientWidth - maxDimension.width) / 2;
19416
- parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height + 1) / 2;
19800
+ parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height) / 2;
19417
19801
  }
19418
19802
  parent.notify('draw', { prop: 'draw-image-to-canvas', value: { dimension: maxDimension } });
19419
19803
  maxDimension.width = this.cropDimension.width;
@@ -20137,7 +20521,7 @@ class Transform {
20137
20521
  maxDimension.height += (maxDimension.height * parent.transform.defaultZoomFactor);
20138
20522
  }
20139
20523
  parent.img.destLeft = (parent.lowerCanvas.clientWidth - maxDimension.width) / 2;
20140
- parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height + 1) / 2;
20524
+ parent.img.destTop = (parent.lowerCanvas.clientHeight - maxDimension.height) / 2;
20141
20525
  if (parent.transform.degree === 0 && parent.transform.currFlipState === '') {
20142
20526
  if (parent.transform.defaultZoomFactor > 0) {
20143
20527
  parent.img.destLeft += parent.panPoint.totalPannedPoint.x;
@@ -20246,11 +20630,11 @@ class Transform {
20246
20630
  const object = { toolbarHeight: 0 };
20247
20631
  const parent = this.parent;
20248
20632
  parent.notify('toolbar', { prop: 'getToolbarHeight', value: { obj: object } });
20249
- let canvasMaxWidth = isImgShape ? parent.element.clientWidth / 3 :
20250
- parent.element.clientWidth;
20251
- let canvasMaxHeight = isImgShape ? (parent.element.clientHeight - object['toolbarHeight']) / 3 :
20252
- parent.element.clientHeight - (object['toolbarHeight']); // 1px border
20253
- canvasMaxHeight = Browser.isDevice ? canvasMaxHeight - (object['toolbarHeight']) : canvasMaxHeight; // 1px border
20633
+ const newWidth = parent.imageSettings.width ? parent.imageSettings.width : parent.element.clientWidth;
20634
+ const newHeight = parent.imageSettings.height ? parent.imageSettings.height : parent.element.clientHeight - (object['toolbarHeight']);
20635
+ let canvasMaxWidth = isImgShape ? parent.element.clientWidth / 3 : newWidth;
20636
+ let canvasMaxHeight = isImgShape ? (parent.element.clientHeight - object['toolbarHeight']) / 3 : newHeight;
20637
+ canvasMaxHeight = Browser.isDevice ? canvasMaxHeight - (object['toolbarHeight']) : canvasMaxHeight;
20254
20638
  if (Browser.isDevice && parent.isStraightening) {
20255
20639
  const cxtTbar = parent.element.querySelector('#' + parent.element.id + '_contextualToolbarArea');
20256
20640
  canvasMaxHeight -= cxtTbar ? cxtTbar.clientHeight : 0;
@@ -20258,7 +20642,8 @@ class Transform {
20258
20642
  if (!isImgShape && parent.element.clientHeight === 0) {
20259
20643
  canvasMaxHeight = 0;
20260
20644
  }
20261
- if (isNullOrUndefined(isImgShape)) {
20645
+ const isImageSettings = parent.imageSettings.width && parent.imageSettings.height ? true : false;
20646
+ if (isNullOrUndefined(isImgShape) && !(isImageSettings)) {
20262
20647
  if (canvasMaxWidth > 30) {
20263
20648
  canvasMaxWidth -= 30;
20264
20649
  }
@@ -20483,6 +20868,9 @@ class Transform {
20483
20868
  this.zoomAction(.0125, null, true, true);
20484
20869
  }
20485
20870
  }
20871
+ if (parent.isPublicMethod && parent.aspectWidth === width && parent.aspectHeight === height) {
20872
+ return;
20873
+ }
20486
20874
  this.resizeImg(activeObj, width, height);
20487
20875
  width = tempwidth;
20488
20876
  height = tempheight;
@@ -20528,9 +20916,12 @@ class Transform {
20528
20916
  value: { type: 'custom', startX: null, startY: null, width: null, height: null } });
20529
20917
  }
20530
20918
  if (isNullOrUndefined(parent.currSelectionPoint)) {
20531
- parent.notify('draw', { prop: 'select', onPropertyChange: false,
20532
- value: { type: 'custom', startX: parent.img.destLeft, startY: parent.img.destTop,
20533
- width: parent.img.destWidth, height: parent.img.destHeight } });
20919
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
20920
+ if (!parent.shapeColl.some((item) => item.rotatedAngle && item.rotatedAngle !== 0)) {
20921
+ parent.notify('draw', { prop: 'select', onPropertyChange: false,
20922
+ value: { type: 'custom', startX: parent.img.destLeft, startY: parent.img.destTop,
20923
+ width: parent.img.destWidth, height: parent.img.destHeight } });
20924
+ }
20534
20925
  }
20535
20926
  else {
20536
20927
  parent.notify('draw', { prop: 'select', onPropertyChange: false,
@@ -20711,6 +21102,8 @@ class UndoRedo {
20711
21102
  this.tempUndoRedoColl = [];
20712
21103
  this.tempUndoRedoStep = 0;
20713
21104
  this.isPreventing = false;
21105
+ this.preventEditComplete = false;
21106
+ this.preventApplyEditComplete = false;
20714
21107
  this.parent = parent;
20715
21108
  this.addEventListener();
20716
21109
  }
@@ -20792,6 +21185,12 @@ class UndoRedo {
20792
21185
  case 'reset':
20793
21186
  this.reset();
20794
21187
  break;
21188
+ case 'preventEditComplete':
21189
+ args.value['obj']['bool'] = this.preventEditComplete;
21190
+ break;
21191
+ case 'preventApplyEditComplete':
21192
+ this.preventApplyEditComplete = args.value['bool'];
21193
+ break;
20795
21194
  }
20796
21195
  }
20797
21196
  getModuleName() {
@@ -20806,6 +21205,7 @@ class UndoRedo {
20806
21205
  this.tempUndoRedoColl = [];
20807
21206
  this.tempUndoRedoStep = 0;
20808
21207
  this.isPreventing = false;
21208
+ this.preventEditComplete = this.preventApplyEditComplete = false;
20809
21209
  }
20810
21210
  refreshUrc(refreshToolbar) {
20811
21211
  const parent = this.parent;
@@ -21517,6 +21917,10 @@ class UndoRedo {
21517
21917
  textArea.style.color = obj.strokeSettings.strokeColor;
21518
21918
  textArea.style.fontWeight = obj.textSettings.bold ? 'bold' : 'normal';
21519
21919
  textArea.style.fontStyle = obj.textSettings.italic ? 'italic' : 'normal';
21920
+ textArea.style.textDecoration = (obj.textSettings.underline && obj.textSettings.strikethrough) ? 'underline line-through' :
21921
+ (obj.textSettings.underline) ? 'underline' :
21922
+ (obj.textSettings.strikethrough) ? 'line-through' :
21923
+ 'none';
21520
21924
  textArea.style.border = '2px solid ' + parent.themeColl[parent.theme]['primaryColor'];
21521
21925
  textArea.value = obj.keyHistory;
21522
21926
  parent.activeObj = extend({}, obj, {}, true);
@@ -21850,6 +22254,7 @@ class UndoRedo {
21850
22254
  const temp = parent.noPushUndo;
21851
22255
  parent.noPushUndo = false;
21852
22256
  parent.isUndoRedoStack = true;
22257
+ this.preventEditComplete = true;
21853
22258
  if (isPenDraw) {
21854
22259
  const tempTogglePen = parent.togglePen;
21855
22260
  const obj = { freehandDrawSelectedId: null };
@@ -21878,7 +22283,14 @@ class UndoRedo {
21878
22283
  parent.enableTextEditing();
21879
22284
  }
21880
22285
  }
21881
- parent.isUndoRedoStack = false;
22286
+ if (this.preventEditComplete) {
22287
+ parent.isUndoRedoStack = this.preventEditComplete = false;
22288
+ if (!this.preventApplyEditComplete) {
22289
+ this.triggerActionCompletedEvent('shape-customize');
22290
+ }
22291
+ this.triggerActionCompletedEvent('shape-select');
22292
+ }
22293
+ parent.isUndoRedoStack = this.preventEditComplete = false;
21882
22294
  }
21883
22295
  }
21884
22296
  }
@@ -22135,6 +22547,12 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
22135
22547
  this.tempRedactBlur = 50;
22136
22548
  /** @hidden */
22137
22549
  this.tempRedactPixel = 40;
22550
+ /** @hidden */
22551
+ this.imageSettings = { width: null, height: null };
22552
+ /** @hidden */
22553
+ this.aspectRatioBaseDimension = false;
22554
+ /** @hidden */
22555
+ this.imageLoaded = false;
22138
22556
  this.tempToolbarHeight = 0;
22139
22557
  this.tempToolbar = [];
22140
22558
  ImageEditor_1.Inject(Crop, Draw, Selection, Transform, Export, ToolbarModule);
@@ -22236,11 +22654,13 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
22236
22654
  break;
22237
22655
  case 'disabled':
22238
22656
  if (newProperties.disabled) {
22239
- this.element.classList.add('e-disabled');
22657
+ this.element.classList.add('e-disabled', 'e-overlay');
22658
+ this.element.style.opacity = '0.5';
22240
22659
  this.unwireEvent();
22241
22660
  }
22242
22661
  else {
22243
- this.element.classList.remove('e-disabled');
22662
+ this.element.classList.remove('e-disabled', 'e-overlay');
22663
+ this.element.style.opacity = '1';
22244
22664
  this.wireEvent();
22245
22665
  }
22246
22666
  break;
@@ -22358,7 +22778,7 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
22358
22778
  if (newProperties.uploadSettings) {
22359
22779
  this.uploadSettings = newProperties.uploadSettings;
22360
22780
  if (!this.uploadSettings.allowedExtensions) {
22361
- this.uploadSettings.allowedExtensions = '.jpg, .jpeg, .png, .svg, .webp';
22781
+ this.uploadSettings.allowedExtensions = '.jpg, .jpeg, .png, .svg, .webp, .bmp';
22362
22782
  this.notify('draw', { prop: 'setNullExtension', value: { extension: true } });
22363
22783
  }
22364
22784
  else {
@@ -22407,6 +22827,10 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
22407
22827
  this.element.innerHTML = '';
22408
22828
  }
22409
22829
  initialize() {
22830
+ if (this.disabled) {
22831
+ this.element.classList.add('e-disabled', 'e-overlay');
22832
+ this.element.style.opacity = '0.5';
22833
+ }
22410
22834
  if (this.toolbarTemplate) {
22411
22835
  this.element.appendChild(this.createElement('div', {
22412
22836
  id: this.element.id + '_toolbarArea', className: 'e-toolbar-area'
@@ -22418,7 +22842,7 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
22418
22842
  this.notify('toolbar', { prop: 'create-contextual-toolbar', onPropertyChange: false });
22419
22843
  }
22420
22844
  if (!this.uploadSettings.allowedExtensions) {
22421
- this.setProperties({ uploadSettings: { allowedExtensions: '.jpg, .jpeg, .png, .svg, .webp' } }, true);
22845
+ this.setProperties({ uploadSettings: { allowedExtensions: '.jpg, .jpeg, .png, .svg, .webp, .bmp' } }, true);
22422
22846
  }
22423
22847
  else {
22424
22848
  this.notify('draw', { prop: 'setNullExtension', value: { extension: false } });
@@ -22618,7 +23042,7 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
22618
23042
  * @returns {string[]}.
22619
23043
  */
22620
23044
  getExtensionArray() {
22621
- const validExtensions = ['jpeg', 'jpg', 'png', 'svg', 'webp'];
23045
+ const validExtensions = ['jpeg', 'jpg', 'png', 'svg', 'webp', 'bmp'];
22622
23046
  const split = this.uploadSettings.allowedExtensions.split(',');
22623
23047
  const extension = [];
22624
23048
  for (const ext of split) {
@@ -22668,6 +23092,9 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
22668
23092
  case 'webp':
22669
23093
  words += ' WebP,';
22670
23094
  break;
23095
+ case 'bmp':
23096
+ words += ' BMP,';
23097
+ break;
22671
23098
  }
22672
23099
  if (i === extension.length - 1) {
22673
23100
  words = words.slice(0, -1);
@@ -22956,10 +23383,16 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
22956
23383
  */
22957
23384
  flip(direction) {
22958
23385
  this.applyShapes();
22959
- this.updateImageTransformColl(direction.toLowerCase() + 'flip');
22960
- this.notify('transform', { prop: 'flip', value: { direction: direction } });
22961
- this.notify('draw', { prop: 'redrawDownScale' });
22962
- this.notify('undo-redo', { prop: 'updateCurrUrc', value: { type: 'ok' } });
23386
+ if (this.activeObj.shape && this.activeObj.shape.indexOf('crop') > -1) {
23387
+ this.transformSelect(direction.toLowerCase() + 'flip');
23388
+ }
23389
+ else {
23390
+ this.updateImageTransformColl(direction.toLowerCase() + 'flip');
23391
+ this.setRotateZoom();
23392
+ this.notify('transform', { prop: 'flip', value: { direction: direction } });
23393
+ this.notify('draw', { prop: 'redrawDownScale' });
23394
+ this.notify('undo-redo', { prop: 'updateCurrUrc', value: { type: 'ok' } });
23395
+ }
22963
23396
  const actionArgs = { action: 'flip', actionEventArgs: this.editCompleteArgs };
22964
23397
  this.triggerEditCompleteEvent(actionArgs);
22965
23398
  }
@@ -22998,7 +23431,7 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
22998
23431
  *
22999
23432
  * @param {string | ImageData } data - Specifies url of the image or image data.
23000
23433
  * @param {boolean} [resetChanges=true] - Optional. Determines whether to reset existing changes when opening the image. The default value is true, which resets all existing changes.
23001
- * @param {ImageSettings} imageSettings - Optional. Specifies the image setting that contains background color to apply when opening a transparent image. The default value of background color is an empty string (''), meaning no background color is applied by default when a transparent image is opened.
23434
+ * @param {ImageSettings} imageSettings - Optional. Specifies image settings to apply when loading an image.
23002
23435
  *
23003
23436
  * @remarks
23004
23437
  * The supported file types are JPG, JPEG, PNG, and SVG.
@@ -23008,14 +23441,85 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23008
23441
  open(data, resetChanges, imageSettings) {
23009
23442
  resetChanges = isNullOrUndefined(resetChanges) ? true : resetChanges;
23010
23443
  if (resetChanges) {
23011
- if (isNullOrUndefined(data)) {
23444
+ if (isNullOrUndefined(data) || this.disabled) {
23012
23445
  return;
23013
23446
  }
23014
23447
  const dropArea = document.getElementById(this.element.id + '_dropArea');
23015
23448
  if (dropArea) {
23016
23449
  dropArea.style.display = 'none';
23017
23450
  }
23018
- this.notify('draw', { prop: 'open', value: { data: data } });
23451
+ this.imageSettings = { width: null, height: null };
23452
+ this.aspectRatioBaseDimension = null;
23453
+ if (imageSettings && (imageSettings.width || imageSettings.height)) {
23454
+ const tempImageSettings = extend({}, imageSettings, {}, true);
23455
+ imageSettings = this.scaleToFit(imageSettings);
23456
+ this.aspectRatioBaseDimension = imageSettings.isAspectRatio;
23457
+ if (!imageSettings.isAspectRatio && imageSettings.width && imageSettings.height) {
23458
+ this.imageSettings.width = imageSettings.width;
23459
+ this.imageSettings.height = imageSettings.height;
23460
+ this.notify('draw', { prop: 'open', value: { data: data } });
23461
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23462
+ const intervalId = setInterval(() => {
23463
+ if (this.imageLoaded && this.baseImg.width && this.baseImg.height) {
23464
+ this.setInitialZoomLevel(tempImageSettings);
23465
+ clearInterval(intervalId);
23466
+ }
23467
+ }, 1);
23468
+ }
23469
+ else if (imageSettings.width || imageSettings.height) {
23470
+ this.notify('draw', { prop: 'open', value: { data: data } });
23471
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23472
+ const intervalId = setInterval(() => {
23473
+ if (this.imageLoaded && this.baseImg.width && this.baseImg.height) {
23474
+ this.imageSettings.width = imageSettings.width;
23475
+ this.imageSettings.height = imageSettings.height;
23476
+ const originalWidth = this.baseImg.width;
23477
+ const originalHeight = this.baseImg.height;
23478
+ let maxValue = '';
23479
+ let aspectRatioValue;
23480
+ let value;
23481
+ let newValue;
23482
+ if (imageSettings.width && imageSettings.height) {
23483
+ maxValue = imageSettings.width > imageSettings.height ? 'width' : 'height';
23484
+ }
23485
+ if (maxValue === 'width' || (imageSettings.width && maxValue !== 'height')) {
23486
+ aspectRatioValue = imageSettings.width;
23487
+ value = aspectRatioValue / (originalWidth / originalHeight);
23488
+ newValue = value % 1 >= 0.5 || value % 1 <= -0.5 ? Math.round(value) : (value < 0) ? Math.ceil(value) : Math.floor(value);
23489
+ if (!imageSettings.height || newValue > imageSettings.height) {
23490
+ this.imageSettings.height = imageSettings.height = newValue;
23491
+ }
23492
+ else {
23493
+ aspectRatioValue = imageSettings.height;
23494
+ value = aspectRatioValue / (originalHeight / originalWidth);
23495
+ newValue = value % 1 >= 0.5 || value % 1 <= -0.5 ? Math.round(value) : (value < 0) ? Math.ceil(value) : Math.floor(value);
23496
+ this.imageSettings.width = imageSettings.width = newValue;
23497
+ }
23498
+ }
23499
+ else if (maxValue === 'height' || (imageSettings.height && maxValue !== 'width')) {
23500
+ aspectRatioValue = imageSettings.height;
23501
+ value = aspectRatioValue / (originalHeight / originalWidth);
23502
+ newValue = value % 1 >= 0.5 || value % 1 <= -0.5 ? Math.round(value) : (value < 0) ? Math.ceil(value) : Math.floor(value);
23503
+ if (!imageSettings.width || newValue > imageSettings.width) {
23504
+ this.imageSettings.width = imageSettings.width = newValue;
23505
+ }
23506
+ else {
23507
+ aspectRatioValue = imageSettings.width;
23508
+ value = aspectRatioValue / (originalWidth / originalHeight);
23509
+ newValue = value % 1 >= 0.5 || value % 1 <= -0.5 ? Math.round(value) : (value < 0) ? Math.ceil(value) : Math.floor(value);
23510
+ this.imageSettings.height = imageSettings.height = newValue;
23511
+ }
23512
+ }
23513
+ this.notify('draw', { prop: 'open', value: { data: data } });
23514
+ this.setInitialZoomLevel(tempImageSettings);
23515
+ clearInterval(intervalId);
23516
+ }
23517
+ }, 1);
23518
+ }
23519
+ }
23520
+ else {
23521
+ this.notify('draw', { prop: 'open', value: { data: data } });
23522
+ }
23019
23523
  }
23020
23524
  else {
23021
23525
  this.updateImage(data, imageSettings ? imageSettings.backgroundColor : null);
@@ -23169,11 +23673,18 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23169
23673
  rotate(degree) {
23170
23674
  const obj = { isRotate: false };
23171
23675
  this.applyShapes();
23172
- if (degree === 90 || degree === -90) {
23173
- this.updateImageTransformColl(degree === 90 ? 'rotateright' : 'rotateleft');
23676
+ if (this.activeObj.shape && this.activeObj.shape.indexOf('crop') > -1) {
23677
+ this.transformSelect(degree === 90 ? 'rotateright' : 'rotateleft');
23678
+ obj['isRotate'] = true;
23679
+ }
23680
+ else {
23681
+ if (degree === 90 || degree === -90) {
23682
+ this.updateImageTransformColl(degree === 90 ? 'rotateright' : 'rotateleft');
23683
+ }
23684
+ this.setRotateZoom();
23685
+ this.notify('transform', { prop: 'rotate', value: { degree: degree, obj: obj } });
23686
+ this.notify('draw', { prop: 'redrawDownScale' });
23174
23687
  }
23175
- this.notify('transform', { prop: 'rotate', value: { degree: degree, obj: obj } });
23176
- this.notify('draw', { prop: 'redrawDownScale' });
23177
23688
  const actionArgs = { action: 'rotate', actionEventArgs: this.editCompleteArgs };
23178
23689
  this.triggerEditCompleteEvent(actionArgs);
23179
23690
  return obj['isRotate'];
@@ -23191,7 +23702,7 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23191
23702
  * @returns {void}.
23192
23703
  */
23193
23704
  export(type, fileName, imageQuality) {
23194
- this.applyShapes();
23705
+ this.manageActiveAction();
23195
23706
  this.notify('export', { prop: 'export', onPropertyChange: false, value: { type: type, fileName: fileName, imgQuality: imageQuality } });
23196
23707
  }
23197
23708
  /**
@@ -23299,6 +23810,17 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23299
23810
  */
23300
23811
  zoom(zoomFactor, zoomPoint) {
23301
23812
  this.isZoomBtnClick = true;
23813
+ let prevZoom = this.transform.zoomFactor;
23814
+ if (prevZoom !== 0) {
23815
+ const zoomObj = { previousZoomValue: null };
23816
+ this.notify('transform', { prop: 'getPreviousZoomValue', value: { obj: zoomObj } });
23817
+ prevZoom = zoomObj.previousZoomValue;
23818
+ }
23819
+ if (zoomFactor !== 1 && prevZoom !== 0 && ((prevZoom < 1 && zoomFactor > 1) || (prevZoom > 1 && zoomFactor < 1))) {
23820
+ this.notify('transform', { prop: 'zoom', onPropertyChange: false,
23821
+ value: { zoomFactor: 1, zoomPoint }
23822
+ });
23823
+ }
23302
23824
  this.notify('transform', { prop: 'zoom', onPropertyChange: false,
23303
23825
  value: { zoomFactor: zoomFactor, zoomPoint: zoomPoint } });
23304
23826
  this.notify('draw', { prop: 'redrawDownScale' });
@@ -23461,10 +23983,12 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23461
23983
  * @param {string} strokeColor - Specifies the outline color of the text annotation.
23462
23984
  * @param {number} strokeWidth - Specifies the outline stroke width of the text annotation.
23463
23985
  * @param {TransformationCollection[]} transformCollection - Specifies the transform collection of the text annotation.
23986
+ * @param {boolean} underline - Specifies whether the text should be underlined.
23987
+ * @param {boolean} strikethrough - Specifies whether the text should have a strikethrough.
23464
23988
  * @returns {boolean}.
23465
23989
  *
23466
23990
  */
23467
- drawText(x, y, text, fontFamily, fontSize, bold, italic, color, isSelected, degree, fillColor, strokeColor, strokeWidth, transformCollection) {
23991
+ drawText(x, y, text, fontFamily, fontSize, bold, italic, color, isSelected, degree, fillColor, strokeColor, strokeWidth, transformCollection, underline, strikethrough) {
23468
23992
  let isText = false;
23469
23993
  const isPointsInRange = this.allowShape(x, y);
23470
23994
  if (!this.disabled && this.isImageLoaded && (isPointsInRange || (isNullOrUndefined(x) && isNullOrUndefined(y)))) {
@@ -23472,7 +23996,7 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23472
23996
  this.manageActiveAction();
23473
23997
  this.notify('shape', { prop: 'drawText', onPropertyChange: false, value: { x: x, y: y, text: text, fontFamily: fontFamily,
23474
23998
  fontSize: fontSize, bold: bold, italic: italic, color: color, isSelected: isSelected, degree: degree, fillColor: fillColor,
23475
- outlineColor: strokeColor, outlineWidth: strokeWidth, transformCollection: transformCollection } });
23999
+ outlineColor: strokeColor, outlineWidth: strokeWidth, transformCollection: transformCollection, underline: underline, strikethrough: strikethrough } });
23476
24000
  this.editCompleted();
23477
24001
  }
23478
24002
  return isText;
@@ -23497,14 +24021,27 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23497
24021
  let isImage = false;
23498
24022
  const isPointsInRange = this.allowShape(x, y);
23499
24023
  if (!this.disabled && this.isImageLoaded && (isPointsInRange || (isNullOrUndefined(x) && isNullOrUndefined(y)))) {
24024
+ if (typeof data === 'string') {
24025
+ try {
24026
+ const request = new XMLHttpRequest();
24027
+ const isBlob = data.indexOf('blob:') === 0;
24028
+ request.open(isBlob ? 'GET' : 'HEAD', data, false);
24029
+ request.send();
24030
+ isImage = request.status >= 200 && request.status < 300;
24031
+ }
24032
+ catch (error) {
24033
+ isImage = false;
24034
+ }
24035
+ }
24036
+ else if (data instanceof ImageData) {
24037
+ if (data.data instanceof Uint8ClampedArray && data.width > 0 && data.height > 0) {
24038
+ isImage = true;
24039
+ }
24040
+ }
23500
24041
  this.manageActiveAction();
23501
- const length = this.objColl.length;
23502
24042
  this.notify('shape', { prop: 'drawImage', onPropertyChange: false, value: { x: x, y: y, width: width, height: height,
23503
24043
  src: data, degree: degree, isAspectRatio: isAspectRatio, opacity: opacity, isSelected: isSelected } });
23504
24044
  this.editCompleted();
23505
- if (this.objColl.length > length) {
23506
- isImage = true;
23507
- }
23508
24045
  }
23509
24046
  return isImage;
23510
24047
  }
@@ -23629,6 +24166,8 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23629
24166
  this.applyShapes();
23630
24167
  this.notify('shape', { prop: 'deleteShape', onPropertyChange: false, value: { id: id, isShape: true } });
23631
24168
  this.editCompleted('shape-delete');
24169
+ this.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: { context: this.lowerContext } });
24170
+ this.notify('draw', { prop: 'clearOuterCanvas', onPropertyChange: false, value: { context: this.upperContext } });
23632
24171
  }
23633
24172
  /**
23634
24173
  * Get particular shapes details based on id of the shape which is drawn on an image editor.
@@ -23840,6 +24379,7 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23840
24379
  let isResized = false;
23841
24380
  if (((width.toString()).length <= 4 && (height.toString()).length <= 4) && (!this.isCircleCrop || isAspectRatio)) {
23842
24381
  this.manageActiveAction();
24382
+ this.isPublicMethod = true;
23843
24383
  this.notify('toolbar', { prop: 'resizeClick', value: { bool: false } });
23844
24384
  const destPoints = { startX: this.img.destLeft, startY: this.img.destTop, width: this.img.destWidth,
23845
24385
  height: this.img.destHeight };
@@ -23875,6 +24415,7 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
23875
24415
  else {
23876
24416
  this.notify('draw', { prop: 'performCancel', value: { isContextualToolbar: null } });
23877
24417
  }
24418
+ this.isPublicMethod = false;
23878
24419
  this.notify('draw', { prop: 'redrawDownScale' });
23879
24420
  }
23880
24421
  return isResized;
@@ -24378,6 +24919,69 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
24378
24919
  }
24379
24920
  }
24380
24921
  // Toolbar related codes
24922
+ scaleToFit(imageSettings) {
24923
+ const tempImageSettings = extend({}, imageSettings, {}, true);
24924
+ const viewPortWidth = this.lowerCanvas.clientWidth;
24925
+ const viewPortHeight = this.lowerCanvas.clientHeight;
24926
+ if (imageSettings.width && imageSettings.height && (imageSettings.width > viewPortWidth ||
24927
+ imageSettings.height > viewPortHeight)) {
24928
+ const widthScale = viewPortWidth / imageSettings.width;
24929
+ const heightScale = viewPortHeight / imageSettings.height;
24930
+ const scale = Math.min(widthScale, heightScale);
24931
+ tempImageSettings.width = Math.round(imageSettings.width * scale);
24932
+ tempImageSettings.height = Math.round(imageSettings.height * scale);
24933
+ }
24934
+ else if (imageSettings.width && imageSettings.width > viewPortWidth) {
24935
+ const scale = viewPortWidth / imageSettings.width;
24936
+ tempImageSettings.width = Math.round(imageSettings.width * scale);
24937
+ }
24938
+ else if (imageSettings.height && imageSettings.height > viewPortHeight) {
24939
+ const scale = viewPortHeight / imageSettings.height;
24940
+ tempImageSettings.height = Math.round(imageSettings.height * scale);
24941
+ }
24942
+ return tempImageSettings;
24943
+ }
24944
+ setInitialZoomLevel(oldImageSettings) {
24945
+ let zoomLevel = 1;
24946
+ let newWidth = this.img.destWidth;
24947
+ let newHeight = this.img.destHeight;
24948
+ const oldWidth = oldImageSettings.width;
24949
+ const oldHeight = oldImageSettings.height;
24950
+ const dimObj = { width: 0, height: 0 };
24951
+ this.notify('transform', { prop: 'calcMaxDimension', onPropertyChange: false,
24952
+ value: { width: this.img.srcWidth, height: this.img.srcHeight, obj: dimObj, isImgShape: null } });
24953
+ while ((newWidth && oldWidth && oldWidth > newWidth) || (newHeight && oldHeight && oldHeight > newHeight)) {
24954
+ newWidth = dimObj['width'] + (dimObj['width'] * 0.025 * zoomLevel);
24955
+ newHeight = dimObj['height'] + (dimObj['height'] * 0.025 * zoomLevel);
24956
+ if (Math.abs(newWidth) >= Math.abs(oldWidth) && Math.abs(newHeight) >= Math.abs(oldHeight)) {
24957
+ break;
24958
+ }
24959
+ zoomLevel++;
24960
+ }
24961
+ if (zoomLevel > 1) {
24962
+ this.isImageLoaded = true;
24963
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24964
+ const intervalId = setInterval(() => {
24965
+ if (this.imageLoaded) {
24966
+ for (let i = 1; i < zoomLevel; i++) {
24967
+ if (Math.round(i / 4) < this.zoomSettings.maxZoomFactor) {
24968
+ this.notify('transform', { prop: 'zoomAction', onPropertyChange: false,
24969
+ value: { zoomFactor: 0.025, zoomPoint: null, isResize: true } });
24970
+ }
24971
+ else {
24972
+ zoomLevel = i;
24973
+ break;
24974
+ }
24975
+ }
24976
+ this.setProperties({ zoomSettings: { zoomFactor: Math.round(zoomLevel / 4) } }, true);
24977
+ this.notify('transform', { prop: 'setPreviousZoomValue', onPropertyChange: false,
24978
+ value: { previousZoomValue: this.zoomSettings.zoomFactor } });
24979
+ this.notify('toolbar', { prop: 'enable-disable-btns' });
24980
+ clearInterval(intervalId);
24981
+ }
24982
+ }, 1);
24983
+ }
24984
+ }
24381
24985
  resetToolbar() {
24382
24986
  if (this.toolbarHeight !== this.tempToolbarHeight && !((isNullOrUndefined(this.toolbar) ||
24383
24987
  (this.toolbar && this.toolbar.length > 0)
@@ -24392,6 +24996,14 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
24392
24996
  this.update();
24393
24997
  }
24394
24998
  }
24999
+ setRotateZoom() {
25000
+ if (this.transform.zoomFactor > 0) {
25001
+ this.notify('draw', { prop: 'setRotateZoom', onPropertyChange: false, value: { isRotateZoom: true } });
25002
+ }
25003
+ else {
25004
+ this.notify('draw', { prop: 'setRotateZoom', onPropertyChange: false, value: { isRotateZoom: false } });
25005
+ }
25006
+ }
24395
25007
  getData(isMaskImage) {
24396
25008
  if (isMaskImage) {
24397
25009
  this.resetToolbar();
@@ -25028,6 +25640,11 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
25028
25640
  }
25029
25641
  }
25030
25642
  triggerEditCompleteEvent(args) {
25643
+ const obj = { bool: false };
25644
+ this.notify('undo-redo', { prop: 'preventEditComplete', value: { obj: obj } });
25645
+ if (obj['bool']) {
25646
+ return;
25647
+ }
25031
25648
  if (args.action === 'shape-insert' && args.actionEventArgs &&
25032
25649
  args.actionEventArgs.currentShapeSettings &&
25033
25650
  args.actionEventArgs.currentShapeSettings.type.toString() === 'Redact') {
@@ -26316,9 +26933,17 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
26316
26933
  this.notify('crop', { prop: 'calcRatio', onPropertyChange: false,
26317
26934
  value: { obj: obj, dimension: { width: ctx.canvas.width, height: ctx.canvas.height } } });
26318
26935
  }
26319
- let dimension;
26320
- // eslint-disable-next-line prefer-const
26321
- dimension = this.getRotatedCanvasDim(this.baseImg.width, this.baseImg.height, this.transform.straighten);
26936
+ let width = this.baseImg.width;
26937
+ let height = this.baseImg.height;
26938
+ if (!this.aspectRatioBaseDimension && this.imageSettings.width && this.imageSettings.height) {
26939
+ const widthRatio = this.baseImg.width / this.imageSettings.width;
26940
+ const heightRatio = this.baseImg.height / this.imageSettings.height;
26941
+ let ratio = (widthRatio + heightRatio) / 2;
26942
+ ratio = ratio < 1 ? 1 : ratio;
26943
+ width = this.imageSettings.width * ratio;
26944
+ height = this.imageSettings.height * ratio;
26945
+ }
26946
+ const dimension = this.getRotatedCanvasDim(width, height, this.transform.straighten);
26322
26947
  this.img.srcWidth = ctx.canvas.width = dimension.width;
26323
26948
  this.img.srcHeight = ctx.canvas.height = dimension.height;
26324
26949
  const x = ctx.canvas.width / 2;
@@ -26326,7 +26951,7 @@ let ImageEditor = ImageEditor_1 = class ImageEditor extends Component {
26326
26951
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
26327
26952
  ctx.translate(x, y);
26328
26953
  ctx.rotate(straighten * Math.PI / 180);
26329
- ctx.drawImage(this.baseImg, -this.baseImg.width / 2, -this.baseImg.height / 2, this.baseImg.width, this.baseImg.height);
26954
+ ctx.drawImage(this.baseImg, -width / 2, -height / 2, width, height);
26330
26955
  ctx.setTransform(1, 0, 0, 1, 0, 0);
26331
26956
  const obj = { width: 0, height: 0 };
26332
26957
  this.notify('crop', { prop: 'calcRatio', onPropertyChange: false, value: { obj: obj, dimension: { width: ctx.canvas.width, height: ctx.canvas.height } } });
@@ -26642,6 +27267,8 @@ var FileType;
26642
27267
  FileType["Svg"] = "Svg";
26643
27268
  /** The WebP file type. */
26644
27269
  FileType["WebP"] = "WebP";
27270
+ /** The BMP file type. */
27271
+ FileType["Bmp"] = "Bmp";
26645
27272
  })(FileType || (FileType = {}));
26646
27273
  /**
26647
27274
  * An enumeration representing the direction of an image editor operation.
@@ -27018,7 +27645,9 @@ class ToolbarModule {
27018
27645
  Path: 'Path',
27019
27646
  Bold: 'Bold',
27020
27647
  Italic: 'Italic',
27648
+ Underline: 'Underline',
27021
27649
  BoldItalic: 'Bold Italic',
27650
+ Strikethrough: 'Strikethrough',
27022
27651
  XSmall: 'X-Small',
27023
27652
  Small: 'Small',
27024
27653
  Medium: 'Medium',
@@ -29082,12 +29711,16 @@ class ToolbarModule {
29082
29711
  if (!Browser.isDevice) {
29083
29712
  const obj = { shape: null };
29084
29713
  parent.notify('selection', { prop: 'getCurrentDrawingShape', value: { obj: obj } });
29085
- if (obj['shape'] !== 'path') {
29714
+ if (obj['shape'] === 'path') {
29715
+ toolbarItems.push({ id: id + '_ok', prefixIcon: 'e-icons e-check', cssClass: 'top-icon e-tick',
29716
+ tooltipText: this.l10n.getConstant('OK'), align: 'Right', tabIndex: 0, disabled: true });
29717
+ }
29718
+ else {
29086
29719
  toolbarItems.push({ id: id + '_ok', prefixIcon: 'e-icons e-check', cssClass: 'top-icon e-tick',
29087
29720
  tooltipText: this.l10n.getConstant('OK'), align: 'Right', tabIndex: 0 });
29088
- toolbarItems.push({ id: id + '_cancel', prefixIcon: 'e-icons e-close', cssClass: 'top-icon e-save',
29089
- tooltipText: this.l10n.getConstant('Cancel'), align: 'Right' });
29090
29721
  }
29722
+ toolbarItems.push({ id: id + '_cancel', prefixIcon: 'e-icons e-close', cssClass: 'top-icon e-save',
29723
+ tooltipText: this.l10n.getConstant('Cancel'), align: 'Right' });
29091
29724
  }
29092
29725
  return toolbarItems;
29093
29726
  }
@@ -29735,6 +30368,14 @@ class ToolbarModule {
29735
30368
  toolbarItems.push({ id: id + '_italic', prefixIcon: 'e-icons e-italic', cssClass: 'top-icon e-italic',
29736
30369
  tooltipText: this.l10n.getConstant('Italic'), align: 'Center' });
29737
30370
  }
30371
+ if (items.indexOf('underline') > -1) {
30372
+ toolbarItems.push({ id: id + '_underline', prefixIcon: 'e-icons e-underline', cssClass: 'top-icon e-underline',
30373
+ tooltipText: this.l10n.getConstant('Underline'), align: 'Center' });
30374
+ }
30375
+ if (items.indexOf('strikethrough') > -1) {
30376
+ toolbarItems.push({ id: id + '_strikethrough', prefixIcon: 'e-icons e-strikethrough', cssClass: 'top-icon e-strikethrough',
30377
+ tooltipText: this.l10n.getConstant('Strikethrough'), align: 'Center' });
30378
+ }
29738
30379
  if (items.indexOf('strokeWidth') > -1) {
29739
30380
  toolbarItems.push({ id: id + '_strokeWidth', cssClass: 'top-icon e-size', tooltipText: this.l10n.getConstant('TextOutlineWidth'), align: 'Center',
29740
30381
  type: 'Input', template: '<button id="' + id + '_borderWidthBtn"></button>' });
@@ -30212,6 +30853,12 @@ class ToolbarModule {
30212
30853
  }
30213
30854
  if (Browser.isDevice) {
30214
30855
  this.initMainToolbar(false, true, true);
30856
+ const okBtn = document.getElementById(parent.element.id + '_ok');
30857
+ const drawingObject = { shape: '' };
30858
+ parent.notify('selection', { prop: 'getCurrentDrawingShape', onPropertyChange: false, value: { obj: drawingObject } });
30859
+ if (drawingObject['shape'] === 'path' && okBtn) {
30860
+ okBtn.classList.add('e-overlay');
30861
+ }
30215
30862
  }
30216
30863
  if (parent.activeObj.shape === 'line' || parent.activeObj.shape === 'path') {
30217
30864
  args.toolbarItems = ['strokeColor', 'strokeWidth', 'z-order', 'duplicate', 'remove'];
@@ -30243,7 +30890,7 @@ class ToolbarModule {
30243
30890
  if (Browser.isDevice) {
30244
30891
  this.initMainToolbar(false, true, true);
30245
30892
  }
30246
- args.toolbarItems = ['fontFamily', 'fontSize', 'fontColor', 'fillColor', 'strokeColor', 'strokeWidth', 'bold', 'italic', 'z-order', 'duplicate', 'remove', 'text'];
30893
+ args.toolbarItems = ['fontFamily', 'fontSize', 'fontColor', 'fillColor', 'strokeColor', 'strokeWidth', 'bold', 'italic', 'underline', 'strikethrough', 'z-order', 'duplicate', 'remove', 'text'];
30247
30894
  this.initTextToolbarItem(args.toolbarItems);
30248
30895
  break;
30249
30896
  case 'pen':
@@ -30379,8 +31026,13 @@ class ToolbarModule {
30379
31026
  parent.notify('transform', { prop: 'getPanMove', onPropertyChange: false,
30380
31027
  value: { obj: panMoveObj } });
30381
31028
  if (panMoveObj['panMove']) {
31029
+ const currentPannedPoint = extend({}, parent.panPoint.currentPannedPoint, {}, true);
31030
+ parent.panPoint.currentPannedPoint = { x: parent.panPoint.totalPannedClientPoint.x, y: parent.panPoint.totalPannedClientPoint.y };
31031
+ parent.panPoint.totalPannedClientPoint = { x: 0, y: 0 };
31032
+ parent.panPoint.totalPannedInternalPoint = { x: 0, y: 0 };
30382
31033
  parent.notify('transform', { prop: 'drawPannedImage', onPropertyChange: false,
30383
- value: { xDiff: null, yDiff: null } });
31034
+ value: { xDiff: parent.panPoint.currentPannedPoint.x, yDiff: parent.panPoint.currentPannedPoint.y } });
31035
+ parent.panPoint.currentPannedPoint = currentPannedPoint;
30384
31036
  }
30385
31037
  }
30386
31038
  updateKBDNavigation(type) {
@@ -32354,60 +33006,10 @@ class ToolbarModule {
32354
33006
  }
32355
33007
  break;
32356
33008
  case 'bold':
32357
- parent.notify('selection', { prop: 'setInitialTextEdit', value: { bool: false } });
32358
- if (parent.activeObj.textSettings.bold && parent.activeObj.textSettings.italic) {
32359
- parent.notify('shape', { prop: 'applyFontStyle', onPropertyChange: false,
32360
- value: { item: 'italic' } });
32361
- }
32362
- else if (parent.activeObj.textSettings.bold && !parent.activeObj.textSettings.italic) {
32363
- parent.notify('shape', { prop: 'applyFontStyle', onPropertyChange: false,
32364
- value: { item: 'default' } });
32365
- }
32366
- else if (!parent.activeObj.textSettings.bold && parent.activeObj.textSettings.italic) {
32367
- parent.notify('shape', { prop: 'applyFontStyle', onPropertyChange: false,
32368
- value: { item: 'bolditalic' } });
32369
- }
32370
- else if (!parent.activeObj.textSettings.bold && !parent.activeObj.textSettings.italic) {
32371
- parent.notify('shape', { prop: 'applyFontStyle', onPropertyChange: false,
32372
- value: { item: 'bold' } });
32373
- }
32374
- if (parent.element.querySelector('#' + id + '_bold').classList.contains('e-selected-btn')) {
32375
- parent.element.querySelector('#' + id + '_bold').classList.remove('e-selected-btn');
32376
- }
32377
- else {
32378
- parent.element.querySelector('#' + id + '_bold').classList.add('e-selected-btn');
32379
- }
32380
- if (parent.activeObj.activePoint.width !== 0 || parent.activeObj.activePoint.height !== 0) {
32381
- parent.notify('undo-redo', { prop: 'updateUndoRedoStack', onPropertyChange: false });
32382
- }
32383
- break;
32384
33009
  case 'italic':
32385
- parent.notify('selection', { prop: 'setInitialTextEdit', value: { bool: false } });
32386
- if (parent.activeObj.textSettings.bold && parent.activeObj.textSettings.italic) {
32387
- parent.notify('shape', { prop: 'applyFontStyle', onPropertyChange: false,
32388
- value: { item: 'bold' } });
32389
- }
32390
- else if (parent.activeObj.textSettings.bold && !parent.activeObj.textSettings.italic) {
32391
- parent.notify('shape', { prop: 'applyFontStyle', onPropertyChange: false,
32392
- value: { item: 'bolditalic' } });
32393
- }
32394
- else if (!parent.activeObj.textSettings.bold && parent.activeObj.textSettings.italic) {
32395
- parent.notify('shape', { prop: 'applyFontStyle', onPropertyChange: false,
32396
- value: { item: 'default' } });
32397
- }
32398
- else if (!parent.activeObj.textSettings.bold && !parent.activeObj.textSettings.italic) {
32399
- parent.notify('shape', { prop: 'applyFontStyle', onPropertyChange: false,
32400
- value: { item: 'italic' } });
32401
- }
32402
- if (parent.element.querySelector('#' + id + '_italic').classList.contains('e-selected-btn')) {
32403
- parent.element.querySelector('#' + id + '_italic').classList.remove('e-selected-btn');
32404
- }
32405
- else {
32406
- parent.element.querySelector('#' + id + '_italic').classList.add('e-selected-btn');
32407
- }
32408
- if (parent.activeObj.activePoint.width !== 0 || parent.activeObj.activePoint.height !== 0) {
32409
- parent.notify('undo-redo', { prop: 'updateUndoRedoStack', onPropertyChange: false });
32410
- }
33010
+ case 'underline':
33011
+ case 'strikethrough':
33012
+ this.toggleStyle(id, type);
32411
33013
  break;
32412
33014
  case 'croptransform':
32413
33015
  this.performCropTransformClick();
@@ -32588,6 +33190,43 @@ class ToolbarModule {
32588
33190
  }
32589
33191
  }
32590
33192
  }
33193
+ getFontStyle(settings) {
33194
+ const parts = [];
33195
+ if (settings.bold) {
33196
+ parts.push('bold');
33197
+ }
33198
+ if (settings.italic) {
33199
+ parts.push('italic');
33200
+ }
33201
+ if (settings.underline) {
33202
+ parts.push('underline');
33203
+ }
33204
+ if (settings.strikethrough) {
33205
+ parts.push('strikethrough');
33206
+ }
33207
+ return parts.length === 0 ? 'default' : parts.join('');
33208
+ }
33209
+ toggleStyle(id, style) {
33210
+ const parent = this.parent;
33211
+ parent.notify('selection', { prop: 'setInitialTextEdit', value: { bool: false } });
33212
+ const settings = parent.activeObj.textSettings;
33213
+ settings[style] = !settings[style];
33214
+ const fontStyle = this.getFontStyle(settings);
33215
+ parent.notify('shape', { prop: 'applyFontStyle', onPropertyChange: false, value: { item: fontStyle } });
33216
+ const button = parent.element.querySelector(`#${id}_${style}`);
33217
+ if (button) {
33218
+ if (button.classList.contains('e-selected-btn')) {
33219
+ button.classList.remove('e-selected-btn');
33220
+ }
33221
+ else {
33222
+ button.classList.add('e-selected-btn');
33223
+ }
33224
+ }
33225
+ if (parent.activeObj.activePoint.width !== 0 ||
33226
+ parent.activeObj.activePoint.height !== 0) {
33227
+ parent.notify('undo-redo', { prop: 'updateUndoRedoStack', onPropertyChange: false });
33228
+ }
33229
+ }
32591
33230
  updateRedactType(value) {
32592
33231
  const parent = this.parent;
32593
33232
  parent.activeObj.redactType = value;
@@ -32606,7 +33245,7 @@ class ToolbarModule {
32606
33245
  if (parent.currObjType.isFiltered || parent.currObjType.isRedact) {
32607
33246
  parent.okBtn();
32608
33247
  }
32609
- if (frame && !frame.classList.contains('e-overlay')) {
33248
+ if (!frame || !frame.classList.contains('e-overlay')) {
32610
33249
  zoom = parent.transform.zoomFactor;
32611
33250
  parent.frameDestPoints = extend({}, parent.img, {}, true);
32612
33251
  if (isNullOrUndefined(parent.cxtTbarHeight)) {
@@ -32615,7 +33254,10 @@ class ToolbarModule {
32615
33254
  this.callFrameToolbar();
32616
33255
  parent.frameObj.type = 'mat';
32617
33256
  this.callFrameToolbar();
32618
- parent.cxtTbarHeight = parent.element.querySelector('#' + id + '_customizeWrapper').scrollHeight;
33257
+ const elem = parent.element.querySelector('#' + id + '_customizeWrapper');
33258
+ if (elem) {
33259
+ parent.cxtTbarHeight = elem.scrollHeight;
33260
+ }
32619
33261
  parent.frameObj = frameObj;
32620
33262
  parent.tempFrameObj = tempFrameObj;
32621
33263
  }
@@ -33178,6 +33820,8 @@ class ToolbarModule {
33178
33820
  const fontSizeElem = parent.element.querySelector('.e-text-font-size');
33179
33821
  const boldBtn = parent.element.querySelector('#' + id + '_bold');
33180
33822
  const italicBtn = parent.element.querySelector('#' + id + '_italic');
33823
+ const underlineBtn = parent.element.querySelector('#' + id + '_underline');
33824
+ const strikethroughBtn = parent.element.querySelector('#' + id + '_strikethrough');
33181
33825
  if (parent.activeObj.strokeSettings && parent.activeObj.textSettings) {
33182
33826
  if (isNullOrUndefined(parent.activeObj.strokeSettings.strokeWidth)) {
33183
33827
  parent.activeObj.strokeSettings.strokeWidth = 2;
@@ -33290,6 +33934,22 @@ class ToolbarModule {
33290
33934
  italicBtn.classList.remove('e-selected-btn');
33291
33935
  }
33292
33936
  }
33937
+ if (underlineBtn) {
33938
+ if (parent.activeObj.textSettings.underline) {
33939
+ underlineBtn.classList.add('e-selected-btn');
33940
+ }
33941
+ else {
33942
+ underlineBtn.classList.remove('e-selected-btn');
33943
+ }
33944
+ }
33945
+ if (strikethroughBtn) {
33946
+ if (parent.activeObj.textSettings.strikethrough) {
33947
+ strikethroughBtn.classList.add('e-selected-btn');
33948
+ }
33949
+ else {
33950
+ strikethroughBtn.classList.remove('e-selected-btn');
33951
+ }
33952
+ }
33293
33953
  if (strokeWidthElem) {
33294
33954
  const width = parent.activeObj.shape === 'text' ? parent.activeObj.strokeSettings.outlineWidth : parent.activeObj.strokeSettings.strokeWidth;
33295
33955
  const strokeWidth = Math.round(width).toString();
@@ -33305,25 +33965,23 @@ class ToolbarModule {
33305
33965
  getStrokeWidth(text) {
33306
33966
  let strokeWidth;
33307
33967
  const currentWidth = parseInt(text, 10) / 2;
33308
- switch (currentWidth) {
33309
- case 0:
33310
- strokeWidth = this.l10n.getConstant('NoOutline');
33311
- break;
33312
- case 1:
33313
- strokeWidth = this.l10n.getConstant('XSmall');
33314
- break;
33315
- case 2:
33316
- strokeWidth = this.l10n.getConstant('Small');
33317
- break;
33318
- case 3:
33319
- strokeWidth = this.l10n.getConstant('Medium');
33320
- break;
33321
- case 4:
33322
- strokeWidth = this.l10n.getConstant('Large');
33323
- break;
33324
- case 5:
33325
- strokeWidth = this.l10n.getConstant('XLarge');
33326
- break;
33968
+ if (currentWidth === 0) {
33969
+ strokeWidth = this.l10n.getConstant('NoOutline');
33970
+ }
33971
+ else if (currentWidth > 0 && currentWidth <= 1) {
33972
+ strokeWidth = this.l10n.getConstant('XSmall');
33973
+ }
33974
+ else if (currentWidth > 1 && currentWidth <= 2) {
33975
+ strokeWidth = this.l10n.getConstant('Small');
33976
+ }
33977
+ else if (currentWidth > 2 && currentWidth <= 3) {
33978
+ strokeWidth = this.l10n.getConstant('Medium');
33979
+ }
33980
+ else if (currentWidth > 3 && currentWidth <= 4) {
33981
+ strokeWidth = this.l10n.getConstant('Large');
33982
+ }
33983
+ else {
33984
+ strokeWidth = this.l10n.getConstant('XLarge');
33327
33985
  }
33328
33986
  return strokeWidth;
33329
33987
  }