Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(fabric.util) add transformPath and joinPath to support text on a path #7300

Merged
merged 8 commits into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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');
});
})();