mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-03-13 16:33:28 -04:00
Remove path to shape guess-work from SVGExport.
This commit is contained in:
parent
c4c7a37993
commit
772f8175e4
1 changed files with 24 additions and 183 deletions
|
@ -37,10 +37,6 @@ new function() {
|
|||
document.createElementNS('http://www.w3.org/2000/svg', tag), attrs);
|
||||
}
|
||||
|
||||
function getDistance(segments, index1, index2) {
|
||||
return segments[index1]._point.getDistance(segments[index2]._point);
|
||||
}
|
||||
|
||||
function getTransform(item, coordinates, center) {
|
||||
var matrix = item._matrix,
|
||||
trans = matrix.getTranslation(),
|
||||
|
@ -80,97 +76,6 @@ new function() {
|
|||
return attrs;
|
||||
}
|
||||
|
||||
function determineAngle(path, segments, type, center) {
|
||||
// If the object is a circle, ellipse, rectangle, or rounded rectangle,
|
||||
// see if it is placed at an angle, by figuring out its topCenter point
|
||||
// and measuring the angle to its center.
|
||||
var topCenter = type === 'rect'
|
||||
? segments[1]._point.add(segments[2]._point).divide(2)
|
||||
: type === 'roundrect'
|
||||
? segments[3]._point.add(segments[4]._point).divide(2)
|
||||
: type === 'circle' || type === 'ellipse'
|
||||
? segments[1]._point
|
||||
: null;
|
||||
var angle = topCenter && topCenter.subtract(center).getAngle() + 90;
|
||||
return Numerical.isZero(angle || 0) ? 0 : angle;
|
||||
}
|
||||
|
||||
function determineType(path, segments) {
|
||||
// Returns true if the the two segment indices are the beggining of two
|
||||
// lines and if the wto lines are parallel.
|
||||
function isColinear(i, j) {
|
||||
var seg1 = segments[i],
|
||||
seg2 = seg1.getNext(),
|
||||
seg3 = segments[j],
|
||||
seg4 = seg3.getNext();
|
||||
return seg1._handleOut.isZero() && seg2._handleIn.isZero()
|
||||
&& seg3._handleOut.isZero() && seg4._handleIn.isZero()
|
||||
&& seg2._point.subtract(seg1._point).isColinear(
|
||||
seg4._point.subtract(seg3._point));
|
||||
}
|
||||
|
||||
function isOrthogonal(i) {
|
||||
var seg2 = segments[i],
|
||||
seg1 = seg2.getPrevious(),
|
||||
seg3 = seg2.getNext();
|
||||
return seg2._point.subtract(seg1._point).isOrthogonal(
|
||||
seg3._point.subtract(seg2._point));
|
||||
}
|
||||
|
||||
// Returns true if the segment at the given index is the beginning of
|
||||
// a orthogonal arc segment. The code is looking at the length of the
|
||||
// handles and their relation to the distance to the imaginary corner
|
||||
// point. If the relation is kappa, then it's an arc.
|
||||
function isArc(i) {
|
||||
var segment = segments[i],
|
||||
next = segment.getNext(),
|
||||
handle1 = segment._handleOut,
|
||||
handle2 = next._handleIn,
|
||||
kappa = Numerical.KAPPA;
|
||||
if (handle1.isOrthogonal(handle2)) {
|
||||
var from = segment._point,
|
||||
to = next._point,
|
||||
// Find the corner point by intersecting the lines described
|
||||
// by both handles:
|
||||
corner = new Line(from, handle1, true).intersect(
|
||||
new Line(to, handle2, true), true);
|
||||
return corner && Numerical.isZero(handle1.getLength() /
|
||||
corner.subtract(from).getLength() - kappa)
|
||||
&& Numerical.isZero(handle2.getLength() /
|
||||
corner.subtract(to).getLength() - kappa);
|
||||
}
|
||||
}
|
||||
|
||||
// See if actually have any curves in the path. Differentiate
|
||||
// between straight objects (line, polyline, rect, and polygon) and
|
||||
// objects with curves(circle, ellipse, roundedRectangle).
|
||||
if (path.isPolygon()) {
|
||||
return segments.length === 4 && path._closed
|
||||
&& isColinear(0, 2) && isColinear(1, 3) && isOrthogonal(1)
|
||||
? 'rect'
|
||||
: segments.length === 0
|
||||
? 'empty'
|
||||
: segments.length >= 3
|
||||
? path._closed ? 'polygon' : 'polyline'
|
||||
: 'line';
|
||||
} else if (path._closed) {
|
||||
if (segments.length === 8
|
||||
&& isArc(0) && isArc(2) && isArc(4) && isArc(6)
|
||||
&& isColinear(1, 5) && isColinear(3, 7)) {
|
||||
return 'roundrect';
|
||||
} else if (segments.length === 4
|
||||
&& isArc(0) && isArc(1) && isArc(2) && isArc(3)) {
|
||||
// If the distance between (point0 and point2) and (point1
|
||||
// and point3) are equal, then it is a circle
|
||||
return Numerical.isZero(getDistance(segments, 0, 2)
|
||||
- getDistance(segments, 1, 3))
|
||||
? 'circle'
|
||||
: 'ellipse';
|
||||
}
|
||||
}
|
||||
return 'path';
|
||||
}
|
||||
|
||||
function exportGroup(item) {
|
||||
var attrs = getTransform(item),
|
||||
children = item._children;
|
||||
|
@ -208,98 +113,34 @@ new function() {
|
|||
|
||||
function exportPath(item) {
|
||||
var segments = item._segments,
|
||||
center = item.getPosition(true),
|
||||
type = determineType(item, segments),
|
||||
angle = determineAngle(item, segments, type, center),
|
||||
type,
|
||||
attrs;
|
||||
switch (type) {
|
||||
case 'empty':
|
||||
if (segments.length === 0)
|
||||
return null;
|
||||
case 'path':
|
||||
if (item.isPolygon()) {
|
||||
if (segments.length >= 3) {
|
||||
type = item._closed ? 'polygon' : 'polyline';
|
||||
var parts = [];
|
||||
for(i = 0, l = segments.length; i < l; i++)
|
||||
parts.push(formatter.point(segments[i]._point));
|
||||
attrs = {
|
||||
points: parts.join(' ')
|
||||
};
|
||||
} else {
|
||||
type = 'line';
|
||||
var first = segments[0]._point,
|
||||
last = segments[segments.length - 1]._point;
|
||||
attrs = {
|
||||
x1: first.x,
|
||||
y1: first.y,
|
||||
x2: last.x,
|
||||
y2: last.y
|
||||
};
|
||||
}
|
||||
} else {
|
||||
type = 'path';
|
||||
var data = item.getPathData();
|
||||
attrs = data && { d: data };
|
||||
break;
|
||||
case 'polyline':
|
||||
case 'polygon':
|
||||
var parts = [];
|
||||
for(i = 0, l = segments.length; i < l; i++)
|
||||
parts.push(formatter.point(segments[i]._point));
|
||||
attrs = {
|
||||
points: parts.join(' ')
|
||||
};
|
||||
break;
|
||||
case 'rect':
|
||||
var width = getDistance(segments, 0, 3),
|
||||
height = getDistance(segments, 0, 1),
|
||||
// Counter-compensate the determined rotation angle
|
||||
point = segments[1]._point.rotate(-angle, center);
|
||||
attrs = {
|
||||
x: point.x,
|
||||
y: point.y,
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
break;
|
||||
case 'roundrect':
|
||||
type = 'rect';
|
||||
// d-variables and point are used to determine the rounded corners
|
||||
// for the rounded rectangle
|
||||
var width = getDistance(segments, 1, 6),
|
||||
height = getDistance(segments, 0, 3),
|
||||
// Subtract side lengths from total width and divide by 2 to get
|
||||
// corner radius size
|
||||
rx = (width - getDistance(segments, 0, 7)) / 2,
|
||||
ry = (height - getDistance(segments, 1, 2)) / 2,
|
||||
// Calculate topLeft corner point, by using sides vectors and
|
||||
// subtracting normalized rx vector to calculate arc corner.
|
||||
left = segments[3]._point, // top-left side point
|
||||
right = segments[4]._point, // top-right side point
|
||||
point = left.subtract(right.subtract(left).normalize(rx))
|
||||
// Counter-compensate the determined rotation angle
|
||||
.rotate(-angle, center);
|
||||
attrs = {
|
||||
x: point.x,
|
||||
y: point.y,
|
||||
width: width,
|
||||
height: height,
|
||||
rx: rx,
|
||||
ry: ry
|
||||
};
|
||||
break;
|
||||
case'line':
|
||||
var first = segments[0]._point,
|
||||
last = segments[segments.length - 1]._point;
|
||||
attrs = {
|
||||
x1: first.x,
|
||||
y1: first.y,
|
||||
x2: last.x,
|
||||
y2: last.y
|
||||
};
|
||||
break;
|
||||
case 'circle':
|
||||
var radius = getDistance(segments, 0, 2) / 2;
|
||||
attrs = {
|
||||
cx: center.x,
|
||||
cy: center.y,
|
||||
r: radius
|
||||
};
|
||||
break;
|
||||
case 'ellipse':
|
||||
var rx = getDistance(segments, 2, 0) / 2,
|
||||
ry = getDistance(segments, 3, 1) / 2;
|
||||
attrs = {
|
||||
cx: center.x,
|
||||
cy: center.y,
|
||||
rx: rx,
|
||||
ry: ry
|
||||
};
|
||||
break;
|
||||
}
|
||||
if (angle) {
|
||||
attrs.transform = 'rotate(' + formatter.number(angle) + ','
|
||||
+ formatter.point(center) + ')';
|
||||
// Tell applyStyle() that to transform the gradient the other way
|
||||
item._gradientMatrix = new Matrix().rotate(-angle, center);
|
||||
}
|
||||
return createElement(type, attrs);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue