From a5a0e90bee4068c6da3399159f16badcc0072956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Thu, 21 Jul 2016 23:07:01 +0200 Subject: [PATCH] Implement PathItem#compare() to support compound-paths. Still needs testing. --- src/path/Path.js | 28 +++++++++++----------------- src/path/PathItem.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/path/Path.js b/src/path/Path.js index a9099baa..0b144216 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -1548,17 +1548,11 @@ var Path = PathItem.extend(/** @lends Path# */{ toPath: '#clone', - /** - * Compares the geometry of two paths to see if they describe the same - * shape, detecting cases where paths start in different segments or even - * use different amounts of curves to describe the same shape, as long as - * their orientation is the same, and their segments and handles really - * result in the same visual appearance of curves. - * - * @param {Path} path the path to compare this path's geometry with - * @return {Boolean} {@true if two paths describe the shame shape} - */ - compare: function(path) { + // NOTE: Documentation is in PathItem#compare() + compare: function compare(path) { + // If a compound-path is involved, redirect to PathItem#compare() + if (!path || path instanceof CompoundPath) + return compare.base.call(this, path); var curves1 = this.getCurves(), curves2 = path.getCurves(), length1 = curves1.length, @@ -1574,15 +1568,15 @@ var Path = PathItem.extend(/** @lends Path# */{ end1 = 0, end2; // First, loop through curves2, looking for the start of the overlapping // sequence with curves1[0]. Also cache curve values for later reuse. - for (var i2 = 0; i2 < length2; i2++) { - var v2 = curves2[i2].getValues(); + for (var i = 0; i < length2; i++) { + var v2 = curves2[i].getValues(); values2.push(v2); var overlaps = Curve.getOverlaps(v1, v2); if (overlaps) { // If the overlap doesn't start at the beginning of v2, then // it can only be the a partial overlap with curves2[0], and // the start is at curves2[-1]: - pos2 = !i2 && overlaps[0][0] > 0 ? length2 - 1 : i2; + pos2 = !i && overlaps[0][0] > 0 ? length2 - 1 : i; // Set end2 to the start of the first overlap on curves2, so // connection checks further down can work. end2 = overlaps[0][1]; @@ -1598,7 +1592,7 @@ var Path = PathItem.extend(/** @lends Path# */{ while (v1 && v2) { var overlaps = Curve.getOverlaps(v1, v2); if (overlaps) { - // Check that the overlaps are joining on curves1 + // Check that the overlaps are joining on curves1. var t1 = overlaps[0][0]; if (abs(t1 - end1) < epsilon) { end1 = overlaps[1][0]; @@ -1608,7 +1602,7 @@ var Path = PathItem.extend(/** @lends Path# */{ v1 = ++pos1 < length1 ? curves1[pos1].getValues() : null; end1 = 0; } - // Check that the overlaps are joining on curves2 + // Check that the overlaps are joining on curves2. var t2 = overlaps[0][1]; if (abs(t2 - end2) < epsilon) { if (!start2) @@ -1627,7 +1621,7 @@ var Path = PathItem.extend(/** @lends Path# */{ // start on curve2, the two paths are not identical. return start2[0] === pos2 && start2[1] === end2; } - // All good, continue to avoid the break; further down + // All good, continue to avoid the break; further down. continue; } } diff --git a/src/path/PathItem.js b/src/path/PathItem.js index d32f845a..8cb7ca56 100644 --- a/src/path/PathItem.js +++ b/src/path/PathItem.js @@ -751,6 +751,48 @@ var PathItem = Item.extend(/** @lends PathItem# */{ } }, + /** + * Compares the geometry of two paths to see if they describe the same + * shape, detecting cases where paths start in different segments or even + * use different amounts of curves to describe the same shape, as long as + * their orientation is the same, and their segments and handles really + * result in the same visual appearance of curves. + * + * @name PathItem#compare + * @function + * + * @param {PathItem} path the path to compare this path's geometry with + * @return {Boolean} {@true if two paths describe the shame shape} + */ + compare: function(path) { + var ok = false; + if (path) { + var paths1 = this._children || [this], + paths2 = path._children.slice() || [path], + length1 = paths1.length, + length2 = paths2.length, + matched = [], + count; + ok = true; + for (var i1 = length1 - 1; i1 >= 0 && ok; i1--) { + var path1 = paths1[i1]; + ok = false; + for (var i2 = length2 - 1; i2 >= 0 && !ok; i2--) { + if (Path.compare(path1, paths2[i2])) { + if (!matched[i2]) { + matched[i2] = true; + count++; + } + ok = true; + } + } + } + // Each path in path2 needs to be matched at least once. + ok = ok && count === length2; + } + return ok; + }, + /** * {@grouptitle Postscript Style Drawing Commands} *