fabric 4.3.0 → 4.4.0

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.
@@ -676,7 +676,10 @@
676
676
  * @chainable true
677
677
  */
678
678
  setViewportTransform: function (vpt) {
679
- var activeObject = this._activeObject, object, i, len;
679
+ var activeObject = this._activeObject,
680
+ backgroundObject = this.backgroundImage,
681
+ overlayObject = this.overlayImage,
682
+ object, i, len;
680
683
  this.viewportTransform = vpt;
681
684
  for (i = 0, len = this._objects.length; i < len; i++) {
682
685
  object = this._objects[i];
@@ -685,6 +688,12 @@
685
688
  if (activeObject) {
686
689
  activeObject.setCoords();
687
690
  }
691
+ if (backgroundObject) {
692
+ backgroundObject.setCoords(true);
693
+ }
694
+ if (overlayObject) {
695
+ overlayObject.setCoords(true);
696
+ }
688
697
  this.calcViewportBoundaries();
689
698
  this.renderOnAddRemove && this.requestRenderAll();
690
699
  return this;
package/src/util/misc.js CHANGED
@@ -969,6 +969,59 @@
969
969
  }).join(' ') + ')';
970
970
  },
971
971
 
972
+ /**
973
+ * given an object and a transform, apply the inverse transform to the object,
974
+ * this is equivalent to remove from that object that transformation, so that
975
+ * added in a space with the removed transform, the object will be the same as before.
976
+ * Removing from an object a transform that scale by 2 is like scaling it by 1/2.
977
+ * Removing from an object a transfrom that rotate by 30deg is like rotating by 30deg
978
+ * in the opposite direction.
979
+ * This util is used to add objects inside transformed groups or nested groups.
980
+ * @memberOf fabric.util
981
+ * @param {fabric.Object} object the object you want to transform
982
+ * @param {Array} transform the destination transform
983
+ */
984
+ removeTransformFromObject: function(object, transform) {
985
+ var inverted = fabric.util.invertTransform(transform),
986
+ finalTransform = fabric.util.multiplyTransformMatrices(inverted, object.calcOwnMatrix());
987
+ fabric.util.applyTransformToObject(object, finalTransform);
988
+ },
989
+
990
+ /**
991
+ * given an object and a transform, apply the transform to the object.
992
+ * this is equivalent to change the space where the object is drawn.
993
+ * Adding to an object a transform that scale by 2 is like scaling it by 2.
994
+ * This is used when removing an object from an active selection for example.
995
+ * @memberOf fabric.util
996
+ * @param {fabric.Object} object the object you want to transform
997
+ * @param {Array} transform the destination transform
998
+ */
999
+ addTransformToObject: function(object, transform) {
1000
+ fabric.util.applyTransformToObject(
1001
+ object,
1002
+ fabric.util.multiplyTransformMatrices(transform, object.calcOwnMatrix())
1003
+ );
1004
+ },
1005
+
1006
+ /**
1007
+ * discard an object transform state and apply the one from the matrix.
1008
+ * @memberOf fabric.util
1009
+ * @param {fabric.Object} object the object you want to transform
1010
+ * @param {Array} transform the destination transform
1011
+ */
1012
+ applyTransformToObject: function(object, transform) {
1013
+ var options = fabric.util.qrDecompose(transform),
1014
+ center = new fabric.Point(options.translateX, options.translateY);
1015
+ object.flipX = false;
1016
+ object.flipY = false;
1017
+ object.set('scaleX', options.scaleX);
1018
+ object.set('scaleY', options.scaleY);
1019
+ object.skewX = options.skewX;
1020
+ object.skewY = options.skewY;
1021
+ object.angle = options.angle;
1022
+ object.setPositionByOrigin(center, 'center', 'center');
1023
+ },
1024
+
972
1025
  /**
973
1026
  * given a width and height, return the size of the bounding box
974
1027
  * that can contains the box with width/height with applied transform
package/src/util/path.js CHANGED
@@ -439,6 +439,17 @@
439
439
  };
440
440
  }
441
441
 
442
+ function getTangentCubicIterator(p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y) {
443
+ return function (pct) {
444
+ var invT = 1 - pct,
445
+ tangentX = (3 * invT * invT * (p2x - p1x)) + (6 * invT * pct * (p3x - p2x)) +
446
+ (3 * pct * pct * (p4x - p3x)),
447
+ tangentY = (3 * invT * invT * (p2y - p1y)) + (6 * invT * pct * (p3y - p2y)) +
448
+ (3 * pct * pct * (p4y - p3y));
449
+ return Math.atan2(tangentY, tangentX);
450
+ };
451
+ }
452
+
442
453
  function QB1(t) {
443
454
  return t * t;
444
455
  }
@@ -461,6 +472,16 @@
461
472
  };
462
473
  }
463
474
 
475
+ function getTangentQuadraticIterator(p1x, p1y, p2x, p2y, p3x, p3y) {
476
+ return function (pct) {
477
+ var invT = 1 - pct,
478
+ tangentX = (2 * invT * (p2x - p1x)) + (2 * pct * (p3x - p2x)),
479
+ tangentY = (2 * invT * (p2y - p1y)) + (2 * pct * (p3y - p2y));
480
+ return Math.atan2(tangentY, tangentX);
481
+ };
482
+ }
483
+
484
+
464
485
  // this will run over a path segment ( a cubic or quadratic segment) and approximate it
465
486
  // with 100 segemnts. This will good enough to calculate the length of the curve
466
487
  function pathIterator(iterator, x1, y1) {
@@ -479,15 +500,16 @@
479
500
  * The percentage will be then used to find the correct point on the canvas for the path.
480
501
  * @param {Array} segInfo fabricJS collection of information on a parsed path
481
502
  * @param {Number} distance from starting point, in pixels.
482
- * @return {Number} length of segment
503
+ * @return {Object} info object with x and y ( the point on canvas ) and angle, the tangent on that point;
483
504
  */
484
505
  function findPercentageForDistance(segInfo, distance) {
485
506
  var perc = 0, tmpLen = 0, iterator = segInfo.iterator, tempP = { x: segInfo.x, y: segInfo.y },
486
- p, nextLen, nextStep = 0.01;
507
+ p, nextLen, nextStep = 0.01, angleFinder = segInfo.angleFinder, lastPerc;
487
508
  // nextStep > 0.0001 covers 0.00015625 that 1/64th of 1/100
488
509
  // the path
489
510
  while (tmpLen < distance && perc <= 1 && nextStep > 0.0001) {
490
511
  p = iterator(perc);
512
+ lastPerc = perc;
491
513
  nextLen = calcLineLength(tempP.x, tempP.y, p.x, p.y);
492
514
  // compare tmpLen each cycle with distance, decide next perc to test.
493
515
  if ((nextLen + tmpLen) > distance) {
@@ -501,6 +523,7 @@
501
523
  tmpLen += nextLen;
502
524
  }
503
525
  }
526
+ p.angle = angleFinder(lastPerc);
504
527
  return p;
505
528
  }
506
529
 
@@ -514,7 +537,7 @@
514
537
  var totalLength = 0, len = path.length, current,
515
538
  //x2 and y2 are the coords of segment start
516
539
  //x1 and y1 are the coords of the current point
517
- x1 = 0, y1 = 0, x2 = 0, y2 = 0, info = [], iterator, tempInfo;
540
+ x1 = 0, y1 = 0, x2 = 0, y2 = 0, info = [], iterator, tempInfo, angleFinder;
518
541
  for (var i = 0; i < len; i++) {
519
542
  current = path[i];
520
543
  tempInfo = {
@@ -544,7 +567,18 @@
544
567
  current[5],
545
568
  current[6]
546
569
  );
570
+ angleFinder = getTangentCubicIterator(
571
+ x1,
572
+ y1,
573
+ current[1],
574
+ current[2],
575
+ current[3],
576
+ current[4],
577
+ current[5],
578
+ current[6]
579
+ );
547
580
  tempInfo.iterator = iterator;
581
+ tempInfo.angleFinder = angleFinder;
548
582
  tempInfo.length = pathIterator(iterator, x1, y1);
549
583
  x1 = current[5];
550
584
  y1 = current[6];
@@ -558,7 +592,16 @@
558
592
  current[3],
559
593
  current[4]
560
594
  );
595
+ angleFinder = getTangentQuadraticIterator(
596
+ x1,
597
+ y1,
598
+ current[1],
599
+ current[2],
600
+ current[3],
601
+ current[4]
602
+ );
561
603
  tempInfo.iterator = iterator;
604
+ tempInfo.angleFinder = angleFinder;
562
605
  tempInfo.length = pathIterator(iterator, x1, y1);
563
606
  x1 = current[3];
564
607
  y1 = current[4];
@@ -584,29 +627,33 @@
584
627
  if (!infos) {
585
628
  infos = getPathSegmentsInfo(path);
586
629
  }
587
- // var distance = infos[infos.length - 1] * perc;
588
630
  var i = 0;
589
631
  while ((distance - infos[i].length > 0) && i < (infos.length - 2)) {
590
632
  distance -= infos[i].length;
591
633
  i++;
592
634
  }
635
+ // var distance = infos[infos.length - 1] * perc;
593
636
  var segInfo = infos[i], segPercent = distance / segInfo.length,
594
- command = segInfo.command, segment = path[i];
637
+ command = segInfo.command, segment = path[i], info;
595
638
 
596
639
  switch (command) {
597
640
  case 'M':
598
- return { x: segInfo.x, y: segInfo.y };
641
+ return { x: segInfo.x, y: segInfo.y, angle: 0 };
599
642
  case 'Z':
600
643
  case 'z':
601
- return new fabric.Point(segInfo.x, segInfo.y).lerp(
644
+ info = new fabric.Point(segInfo.x, segInfo.y).lerp(
602
645
  new fabric.Point(segInfo.destX, segInfo.destY),
603
646
  segPercent
604
647
  );
648
+ info.angle = Math.atan2(segInfo.destY - segInfo.y, segInfo.destX - segInfo.x);
649
+ return info;
605
650
  case 'L':
606
- return new fabric.Point(segInfo.x, segInfo.y).lerp(
651
+ info = new fabric.Point(segInfo.x, segInfo.y).lerp(
607
652
  new fabric.Point(segment[1], segment[2]),
608
653
  segPercent
609
654
  );
655
+ info.angle = Math.atan2(segment[2] - segInfo.y, segment[1] - segInfo.x);
656
+ return info;
610
657
  case 'C':
611
658
  return findPercentageForDistance(segInfo, distance);
612
659
  case 'Q':