blob: 93671ce20f39fb296971336af31920a0027b8a17 [file] [log] [blame]
function MergePathModifier(){
}
extendPrototype([ShapeModifier], MergePathModifier);
MergePathModifier.prototype.initModifierProperties = function(elem, data) {
this.styles = [];
this.caches = [];
this.lStr = '';
var shapeProperty = ShapePropertyFactory.getShapeProp(this,{ks:{a:0,k:{v:[[0,0]],i:[[0,0]],o:[[0,0]],c:true}}},4);
this.sh = shapeProperty;
this.merge_mode = data.mm;
//this.transformers = transformers;
//this.lvl = level;
switch(data.mm) {
case 2:
this.mode = Module.PathOp.UNION;
break;
case 3:
this.mode = Module.PathOp.DIFFERENCE;
//merge_mode = Module.PathOp.REVERSE_DIFFERENCE;
break;
case 4:
this.mode = Module.PathOp.INTERSECT;
break;
case 5:
this.mode = Module.PathOp.XOR;
break;
default:
this.mode = 'none';
}
this.getValue = this.processKeys;
};
MergePathModifier.prototype.setTransformData = function(transformers, level) {
this.transformers = transformers;
this.level = level;
}
MergePathModifier.prototype.setAsAnimated = function() {
this._isAnimated = true;
}
MergePathModifier.prototype.transformPoint = function(point, transformers, level) {
var matrix;
var iterations = level - this.level;
var k = transformers.length-1;
while(iterations) {
matrix = transformers[k].mProps.v;
point = matrix.applyToPointArray(point[0], point[1], 0);
iterations --;
k --;
}
return point;
}
MergePathModifier.prototype.addPathToCommands = function(path, transformers, level, commands) {
var i, len = path._length;
var pt1, pt2, pt3;
pt1 = this.transformPoint(path.v[0], transformers, level);
commands.push([Module.MOVE_VERB, pt1[0], pt1[1]]);
for(i = 0; i < len - 1; i += 1) {
pt1 = this.transformPoint(path.o[i], transformers, level);
pt2 = this.transformPoint(path.i[i + 1], transformers, level);
pt3 = this.transformPoint(path.v[i + 1], transformers, level);
commands.push([Module.CUBIC_VERB, pt1[0], pt1[1], pt2[0], pt2[1], pt3[0], pt3[1]]);
}
if(path.c) {
pt1 = this.transformPoint(path.o[len - 1], transformers, level);
pt2 = this.transformPoint(path.i[0], transformers, level);
pt3 = this.transformPoint(path.v[0], transformers, level);
commands.push([Module.CUBIC_VERB, pt1[0], pt1[1], pt2[0], pt2[1], pt3[0], pt3[1]]);
commands.push([Module.CLOSE_VERB]);
}
}
// _PAPER_FUNCTION
MergePathModifier.prototype.addPathToCommands_PAPER_FUNCTION = function(path, transformers, level, paper_path) {
var i, len = path._length;
var pt1, pt2, pt3;
var segment;
for(i = 0; i < len; i += 1) {
pt1 = this.transformPoint(path.v[i], transformers, level);
pt2 = this.transformPoint(path.i[i], transformers, level);
pt3 = this.transformPoint(path.o[i], transformers, level);
segment = new paper.Segment(new paper.Point(pt1[0],pt1[1])
, new paper.Point(pt2[0] - pt1[0], pt2[1] - pt1[1])
, new paper.Point(pt3[0] - pt1[0], pt3[1] - pt1[1]))
paper_path.add(segment);
}
if(path.c) {
paper_path.closed = true;
}
return paper_path
}
MergePathModifier.prototype.floatTypedArrayFrom2D = function(arr) {
// expects 2d array where index 0 is verb and index 1-n are args
var len = 0, cmd, c, ii, jj;
for (ii = 0; ii < arr.length; ii += 1) {
len += arr[ii].length;
}
var ta = new Float32Array(len);
var i = 0;
for (ii = 0; ii < arr.length; ii += 1) {
for (jj = 0; jj < arr[ii].length; jj += 1) {
ta[i] = arr[ii][jj];
i++;
}
}
var retVal = Module._malloc(ta.length * ta.BYTES_PER_ELEMENT);
Module.HEAPF32.set(ta, retVal / ta.BYTES_PER_ELEMENT);
return [retVal, len];
}
MergePathModifier.prototype.SkPathFromCmdTyped = function(cmdArr) {
var typedArrayFrom2D = this.floatTypedArrayFrom2D(cmdArr);
var cmd = typedArrayFrom2D[0];
var len = typedArrayFrom2D[1];
var path = Module.FromCmds(cmd, len);
Module._free(cmd);
return path;
}
MergePathModifier.prototype.addShapeToCommands = function(shape, transformers, level, commands) {
var i, len = shape.paths._length;
for(i = 0; i < len; i += 1) {
this.addPathToCommands(shape.paths.shapes[i], transformers, level, commands);
}
}
// _PAPER_FUNCTION
MergePathModifier.prototype.addShapeToCommands_PAPER_FUNCTION = function(shape, transformers, level) {
var paper_path = new paper.Path();
var i, len = shape.paths._length;
for(i = 0; i < len; i += 1) {
this.addPathToCommands_PAPER_FUNCTION(shape.paths.shapes[i], transformers, level, paper_path);
}
return paper_path;
}
MergePathModifier.prototype.getPath = function(shapes) {
var commands = [];
var i = 0, len = shapes.length;
var builder = new Module.SkOpBuilder();
var skPath;
var current_shape_merge_mode;
var merge_mode = this.mode;
var isFirstShape = false;
var shapeData, shape;
for(i = len - 1; i >= 0; i -= 1) {
shapeData = shapes[i];
shape = shapeData.shape;
this.addShapeToCommands(shape, shapeData.data.transformers, shapeData.data.lvl, commands);
if(merge_mode !== 'none') {
if(!isFirstShape && (merge_mode === Module.PathOp.DIFFERENCE || merge_mode === Module.PathOp.REVERSE_DIFFERENCE || merge_mode === Module.PathOp.INTERSECT)) {
current_shape_merge_mode = Module.PathOp.UNION;
} else {
current_shape_merge_mode = merge_mode;
}
if(commands.length) {
isFirstShape = true;
skPath = this.SkPathFromCmdTyped(commands);
builder.add(skPath, current_shape_merge_mode);
skPath.delete();
commands.length = 0;
}
}
shape.paths = shapeData.localShapeCollection;
}
if(merge_mode === 'none') {
skPath = this.SkPathFromCmdTyped(commands);
} else {
skPath = builder.resolve();
builder.delete();
}
commands = skPath.toCmds();
skPath.delete();
return commands;
}
MergePathModifier.prototype.PathToCommands = function(path, commands) {
var segments = path.segments;
if(!segments.length) {
return;
}
var i, len = segments.length;
var pt1, pt2, pt3, prev_pt;
pt1 = segments[0].point;
commands.push([0,pt1.x, pt1.y]);
for(i = 1; i < len; i += 1) {
prev_pt = segments[i - 1].point;
pt1 = segments[i - 1].handleOut;
pt2 = segments[i].handleIn;
pt3 = segments[i].point;
commands.push([4,prev_pt.x + pt1.x, prev_pt.y + pt1.y,pt3.x + pt2.x, pt3.y + pt2.y,pt3.x, pt3.y]);
}
prev_pt = segments[len - 1].point;
pt1 = segments[len - 1].handleOut;
pt2 = segments[0].handleIn;
pt3 = segments[0].point;
commands.push([4,prev_pt.x + pt1.x, prev_pt.y + pt1.y,pt3.x + pt2.x, pt3.y + pt2.y,pt3.x, pt3.y]);
commands.push([5]);
}
MergePathModifier.prototype.toCmds = function(path) {
var commands = [];
if(path.children) {
var i, len = path.children.length;
for(i = 0; i < len; i += 1) {
this.PathToCommands(path.children[i], commands);
}
} else {
this.PathToCommands(path, commands);
}
return commands;
//console.log(commands)
}
// _PAPER_FUNCTION
MergePathModifier.prototype.getPath_PAPER_FUNCTION = function(shapes) {
var paper_path = [];
var i = 0, len = shapes.length;
var skPath;
var current_shape_merge_mode;
var merge_mode = this.mode;
var isFirstShape = false;
var prev_path;
for(i = len - 1; i >= 0; i -= 1) {
shapeData = shapes[i];
shape = shapeData.shape;
paper_path = this.addShapeToCommands_PAPER_FUNCTION(shape, shapeData.data.transformers, shapeData.data.lvl);
if(prev_path) {
if(this.merge_mode === 2) {
prev_path = prev_path.unite(paper_path);
} else {
prev_path = prev_path.intersect(paper_path);
}
} else if(paper_path.segments.length) {
prev_path = paper_path;
}
shape.paths = shapeData.localShapeCollection;
}
return this.toCmds(prev_path);
}
MergePathModifier.prototype.checkIfHasModified = function(shapeData) {
if(shapeData.shape._mdf) {
return true;
}
var transforms = shapeData.data.transformers;
var i = 0, len = transforms.length;
while(i < len) {
if(transforms[i].mProps._mdf) {
return true;
}
i += 1;
}
return false;
}
MergePathModifier.prototype.processShapes = function(_isFirstFrame) {
if(window.global_properties.use_paper_library) {
paper.project.activeLayer.removeChildren();
}
var commands = [];
var i = 0, len = this.shapes.length;
var shapeData, shape, skPath;
var hasNewShapes = false;
while(i < len) {
if(this.checkIfHasModified(this.shapes[i])) {
hasNewShapes = true;
break;
}
i += 1;
}
if(!hasNewShapes && !_isFirstFrame) {
this.sh._mdf = false;
for(i = 0; i < len; i += 1) {
shapeData = this.shapes[i];
shapeData.shape.paths = shapeData.localShapeCollection;
}
} else {
if(window.global_properties.use_paper_library) {
commands = this.getPath_PAPER_FUNCTION(this.shapes);
} else {
commands = this.getPath(this.shapes);
}
var shapeData = this.sh;
var localShapeCollection = shapeData.localShapeCollection;
localShapeCollection = this.createPathFromCommands(commands, localShapeCollection);
shapeData._mdf = true;
shapeData.paths = shapeData.localShapeCollection;
}
}
MergePathModifier.prototype.createPathFromCommands = function(commands, localShapeCollection) {
var i, len;
var shapeData = this.sh;
var localShapeCollection = shapeData.localShapeCollection;
localShapeCollection.releaseShapes();
var i, len = commands.length;
var new_path;
var node_index = 0;
var hasClosedPath = false;
var command, prev_command;
for(i = 0; i < len; i += 1) {
command = commands[i];
if(command[0] === 0) {
if(new_path) {
if(!hasClosedPath) {
prev_command = commands[i - 1];
new_path.setXYAt(prev_command[prev_command.length - 2], prev_command[prev_command.length - 1], 'o', new_path._length - 1, false);
}
localShapeCollection.addShape(new_path);
}
hasClosedPath = false;
node_index = 0;
new_path = shape_pool.newElement();
new_path.setXYAt(command[1], command[2], 'v', node_index, false);
new_path.setXYAt(command[1], command[2], 'i', node_index, false);
node_index += 1;
} else if(command[0] === 1) {
prev_command = commands[i - 1];
new_path.setXYAt(command[1], command[2], 'v', node_index, false);
new_path.setXYAt(prev_command[prev_command.length - 2], prev_command[prev_command.length - 1], 'o',node_index - 1, false);
new_path.setXYAt(command[1], command[2], 'i', node_index, false);
node_index += 1;
} else if(command[0] === 4) {
new_path.setXYAt(command[5], command[6], 'v', node_index, false);
new_path.setXYAt(command[1], command[2], 'o', node_index - 1, false);
new_path.setXYAt(command[3], command[4], 'i', node_index, false);
node_index += 1;
} else if(command[0] === 5) {
prev_command = commands[i - 1];
new_path.c = true;
new_path.setXYAt(prev_command[prev_command.length - 2], prev_command[prev_command.length - 1], 'o', node_index - 1, false);
node_index += 1;
hasClosedPath = true;
}
}
if(new_path) {
if(!hasClosedPath) {
prev_command = commands[i - 1];
new_path.setXYAt(prev_command[prev_command.length - 2], prev_command[prev_command.length - 1], 'o', new_path._length - 1, false);
}
localShapeCollection.addShape(new_path);
}
return localShapeCollection;
}
ShapeModifiers.registerModifier('mm', MergePathModifier);