Skip to content

Commit

Permalink
feat(fabric.util) add transformPath and joinPath to support text on a…
Browse files Browse the repository at this point in the history
… path (#7300)
  • Loading branch information
asturur authored Aug 27, 2021
1 parent a7fae08 commit 6790696
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 14 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Changelog

## [next]
## [4.6.0]

- feat(fabric.util): added fabric.util.transformPath to add transformations to path points [#7300](https://github.com/fabricjs/fabric.js/pull/7300)
- feat(fabric.util): added fabric.util.joinPath, the opposite of fabric.util.parsePath [#7300](https://github.com/fabricjs/fabric.js/pull/7300)
- fix(fabric.util): use integers iterators [#7233](https://github.com/fabricjs/fabric.js/pull/7233)
- feat(fabric.Text) add path rendering to text on path [#7328](https://github.com/fabricjs/fabric.js/pull/7328)
- feat(fabric.iText): Add optional hiddenTextareaContainer to contain hiddenTextarea [#7314](https://github.com/fabricjs/fabric.js/pull/7314)
Expand Down
2 changes: 1 addition & 1 deletion src/brushes/pencil_brush.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@
* @returns {boolean}
*/
_isEmptySVGPath: function (pathData) {
var pathString = pathData.map(function (segment) { return segment.join(' '); }).join(' ');
var pathString = fabric.util.joinPath(pathData);
return pathString === 'M 0 0 Q 0 0 0 0 L 0 0';
},

Expand Down
13 changes: 4 additions & 9 deletions src/shapes/path.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,9 @@

var fromArray = _toString.call(path) === '[object Array]';

this.path = fromArray
? fabric.util.makePathSimpler(path)

: fabric.util.makePathSimpler(
fabric.util.parsePath(path)
);
this.path = fabric.util.makePathSimpler(
fromArray ? path : fabric.util.parsePath(path)
);

if (!this.path) {
return;
Expand Down Expand Up @@ -193,9 +190,7 @@
* of the instance
*/
_toSVG: function() {
var path = this.path.map(function(path) {
return path.join(' ');
}).join(' ');
var path = fabric.util.joinPath(this.path);
return [
'<path ', 'COMMON_PARTS',
'd="', path,
Expand Down
44 changes: 41 additions & 3 deletions src/util/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,36 @@
path.push(['L', p1.x + multSignX * correction, p1.y + multSignY * correction]);
return path;
}
/**
* Transform a path by transforming each segment.
* it has to be a simplified path or it won't work.
* WARNING: this depends from pathOffset for correct operation
* @param {Array} path fabricJS parsed and simplified path commands
* @param {Array} transform matrix that represent the transformation
* @param {Object} [pathOffset] the fabric.Path pathOffset
* @param {Number} pathOffset.x
* @param {Number} pathOffset.y
* @returns {Array} the transformed path
*/
function transformPath(path, transform, pathOffset) {
if (pathOffset) {
transform = fabric.util.multiplyTransformMatrices(
transform,
[1, 0, 0, 1, -pathOffset.x, -pathOffset.y]
);
}
return path.map(function(pathSegment) {
var newSegment = pathSegment.slice(0), point = {};
for (var i = 1; i < pathSegment.length - 1; i += 2) {
point.x = pathSegment[i];
point.y = pathSegment[i + 1];
point = fabric.util.transformPoint(point, transform);
newSegment[i] = point.x;
newSegment[i + 1] = point.y;
}
return newSegment;
});
}

/**
* Calculate bounding box of a elliptic-arc
Expand Down Expand Up @@ -825,19 +855,27 @@
});
};

/**
* Join path commands to go back to svg format
* @param {Array} pathData fabricJS parsed path commands
* @return {String} joined path 'M 0 0 L 20 30'
*/
fabric.util.joinPath = function(pathData) {
return pathData.map(function (segment) { return segment.join(' '); }).join(' ');
};
fabric.util.parsePath = parsePath;
fabric.util.makePathSimpler = makePathSimpler;
fabric.util.getSmoothPathFromPoints = getSmoothPathFromPoints;
fabric.util.getPathSegmentsInfo = getPathSegmentsInfo;
fabric.util.fromArcToBeziers = fromArcToBeziers;
fabric.util.getBoundsOfCurve = getBoundsOfCurve;
fabric.util.getPointOnPath = getPointOnPath;
fabric.util.transformPath = transformPath;
/**
* Typo of `fromArcToBeziers` kept for not breaking the api once corrected.
* Will be removed in fabric 5.0
* @deprecated
*/
fabric.util.fromArcToBeizers = fromArcToBeziers;
fabric.util.getBoundsOfCurve = getBoundsOfCurve;
fabric.util.getPointOnPath = getPointOnPath;
// kept because we do not want to make breaking changes.
// but useless and deprecated.
fabric.util.getBoundsOfArc = getBoundsOfArc;
Expand Down
16 changes: 16 additions & 0 deletions test/unit/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -1090,4 +1090,20 @@
assert.notOk(fabric.util.isTouchEvent({ type: 'mousedown' }));
assert.notOk(fabric.util.isTouchEvent({ pointerType: 'mouse' }));
});

QUnit.test('fabric.util.transformPath can scale a path by 2', function(assert) {
assert.ok(typeof fabric.util.transformPath === 'function');
var path = new fabric.Path('M 100 100 L 200 100 L 170 200 z');
var oldPath = path.path;
var newPath = fabric.util.transformPath(path.path, [2, 0, 0, 2, 0, 0]);
assert.equal(fabric.util.joinPath(oldPath), 'M 100 100 L 200 100 L 170 200 z');
assert.equal(fabric.util.joinPath(newPath), 'M 200 200 L 400 200 L 340 400 z');
});
QUnit.test('fabric.util.transformPath can apply a generic transform', function(assert) {
var path = new fabric.Path('M 100 100 L 200 100 L 170 200 z');
var oldPath = path.path;
var newPath = fabric.util.transformPath(path.path, [1, 2, 3, 4, 5, 6], path.pathOffset);
assert.equal(fabric.util.joinPath(oldPath), 'M 100 100 L 200 100 L 170 200 z');
assert.equal(fabric.util.joinPath(newPath), 'M -195 -294 L -95 -94 L 175 246 z');
});
})();

0 comments on commit 6790696

Please sign in to comment.