lepu-test-platform-web/node_modules/svgo/plugins/transformsWithOnePath.js

328 lines
11 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
/*
* Thanks to http://fontello.com project for sponsoring this plugin
*/
exports.type = 'full';
exports.active = false;
exports.description = 'performs a set of operations on SVG with one path inside (disabled by default)';
exports.params = {
// width and height to resize SVG and rescale inner Path
width: false,
height: false,
// scale inner Path without resizing SVG
scale: false,
// shiftX/Y inner Path
shiftX: false,
shiftY: false,
// crop SVG width along the real width of inner Path
hcrop: false,
// vertical center inner Path inside SVG height
vcenter: false,
// stringify params
floatPrecision: 3,
leadingZero: true,
negativeExtraSpace: true
};
var _path = require('./_path.js'),
relative2absolute = _path.relative2absolute,
computeCubicBoundingBox = _path.computeCubicBoundingBox,
computeQuadraticBoundingBox = _path.computeQuadraticBoundingBox,
applyTransforms = _path.applyTransforms,
js2path = _path.js2path,
path2js = _path.path2js,
EXTEND = require('whet.extend');
exports.fn = function(data, params) {
data.content.forEach(function(item) {
// only for SVG with one Path inside
if (item.isElem('svg') &&
item.content.length === 1 &&
item.content[0].isElem('path')
) {
var svgElem = item,
pathElem = svgElem.content[0],
// get absoluted Path data
path = relative2absolute(EXTEND(true, [], path2js(pathElem))),
xs = [],
ys = [],
cubicСontrolPoint = [0, 0],
quadraticСontrolPoint = [0, 0],
lastPoint = [0, 0],
cubicBoundingBox,
quadraticBoundingBox,
i,
segment;
path.forEach(function(pathItem) {
// ML
if ('ML'.indexOf(pathItem.instruction) > -1) {
for (i = 0; i < pathItem.data.length; i++) {
if (i % 2 === 0) {
xs.push(pathItem.data[i]);
} else {
ys.push(pathItem.data[i]);
}
}
lastPoint = cubicСontrolPoint = quadraticСontrolPoint = pathItem.data.slice(-2);
// H
} else if (pathItem.instruction === 'H') {
pathItem.data.forEach(function(d) {
xs.push(d);
});
lastPoint[0] = cubicСontrolPoint[0] = quadraticСontrolPoint[0] = pathItem.data[pathItem.data.length - 2];
// V
} else if (pathItem.instruction === 'V') {
pathItem.data.forEach(function(d) {
ys.push(d);
});
lastPoint[1] = cubicСontrolPoint[1] = quadraticСontrolPoint[1] = pathItem.data[pathItem.data.length - 1];
// C
} else if (pathItem.instruction === 'C') {
for (i = 0; i < pathItem.data.length; i += 6) {
segment = pathItem.data.slice(i, i + 6);
cubicBoundingBox = computeCubicBoundingBox.apply(this, lastPoint.concat(segment));
xs.push(cubicBoundingBox.minx);
xs.push(cubicBoundingBox.maxx);
ys.push(cubicBoundingBox.miny);
ys.push(cubicBoundingBox.maxy);
// reflected control point for the next possible S
cubicСontrolPoint = [
2 * segment[4] - segment[2],
2 * segment[5] - segment[3]
];
lastPoint = segment.slice(-2);
}
// S
} else if (pathItem.instruction === 'S') {
for (i = 0; i < pathItem.data.length; i += 4) {
segment = pathItem.data.slice(i, i + 4);
cubicBoundingBox = computeCubicBoundingBox.apply(this, lastPoint.concat(cubicСontrolPoint).concat(segment));
xs.push(cubicBoundingBox.minx);
xs.push(cubicBoundingBox.maxx);
ys.push(cubicBoundingBox.miny);
ys.push(cubicBoundingBox.maxy);
// reflected control point for the next possible S
cubicСontrolPoint = [
2 * segment[2] - cubicСontrolPoint[0],
2 * segment[3] - cubicСontrolPoint[1],
];
lastPoint = segment.slice(-2);
}
// Q
} else if (pathItem.instruction === 'Q') {
for (i = 0; i < pathItem.data.length; i += 4) {
segment = pathItem.data.slice(i, i + 4);
quadraticBoundingBox = computeQuadraticBoundingBox.apply(this, lastPoint.concat(segment));
xs.push(quadraticBoundingBox.minx);
xs.push(quadraticBoundingBox.maxx);
ys.push(quadraticBoundingBox.miny);
ys.push(quadraticBoundingBox.maxy);
// reflected control point for the next possible T
quadraticСontrolPoint = [
2 * segment[2] - segment[0],
2 * segment[3] - segment[1]
];
lastPoint = segment.slice(-2);
}
// S
} else if (pathItem.instruction === 'T') {
for (i = 0; i < pathItem.data.length; i += 2) {
segment = pathItem.data.slice(i, i + 2);
quadraticBoundingBox = computeQuadraticBoundingBox.apply(this, lastPoint.concat(quadraticСontrolPoint).concat(segment));
xs.push(quadraticBoundingBox.minx);
xs.push(quadraticBoundingBox.maxx);
ys.push(quadraticBoundingBox.miny);
ys.push(quadraticBoundingBox.maxy);
// reflected control point for the next possible T
quadraticСontrolPoint = [
2 * segment[0] - quadraticСontrolPoint[0],
2 * segment[1] - quadraticСontrolPoint[1]
];
lastPoint = segment.slice(-2);
}
}
});
var xmin = Math.min.apply(this, xs).toFixed(params.floatPrecision),
xmax = Math.max.apply(this, xs).toFixed(params.floatPrecision),
ymin = Math.min.apply(this, ys).toFixed(params.floatPrecision),
ymax = Math.max.apply(this, ys).toFixed(params.floatPrecision),
svgWidth = +svgElem.attr('width').value,
svgHeight = +svgElem.attr('height').value,
realWidth = Math.round(xmax - xmin),
realHeight = Math.round(ymax - ymin),
transform = '',
scale;
// width & height
if (params.width && params.height) {
scale = Math.min(params.width / svgWidth, params.height / svgHeight);
realWidth = realWidth * scale;
realHeight = realHeight * scale;
svgWidth = svgElem.attr('width').value = params.width;
svgHeight = svgElem.attr('height').value = params.height;
transform += ' scale(' + scale + ')';
// width
} else if (params.width && !params.height) {
scale = params.width / svgWidth;
realWidth = realWidth * scale;
realHeight = realHeight * scale;
svgWidth = svgElem.attr('width').value = params.width;
svgHeight = svgElem.attr('height').value = svgHeight * scale;
transform += ' scale(' + scale + ')';
// height
} else if (params.height && !params.width) {
scale = params.height / svgHeight;
realWidth = realWidth * scale;
realHeight = realHeight * scale;
svgWidth = svgElem.attr('width').value = svgWidth * scale;
svgHeight = svgElem.attr('height').value = params.height;
transform += ' scale(' + scale + ')';
}
// shiftX
if (params.shiftX) {
transform += ' translate(' + realWidth * params.shiftX + ', 0)';
}
// shiftY
if (params.shiftY) {
transform += ' translate(0, ' + realHeight * params.shiftY + ')';
}
// scale
if (params.scale) {
scale = params.scale;
var shiftX = svgWidth / 2,
shiftY = svgHeight / 2;
realWidth = realWidth * scale;
realHeight = realHeight * scale;
if (params.shiftX || params.shiftY) {
transform += ' scale(' + scale + ')';
} else {
transform += ' translate(' + shiftX + ' ' + shiftY + ') scale(' + scale + ') translate(-' + shiftX + ' -' + shiftY + ')';
}
}
// hcrop
if (params.hcrop) {
transform += ' translate(' + (-xmin) + ' 0)';
svgElem.attr('width').value = realWidth;
}
// vcenter
if (params.vcenter) {
transform += ' translate(0 ' + (((svgHeight - realHeight) / 2) - ymin) + ')';
}
if (transform) {
pathElem.addAttr({
name: 'transform',
prefix: '',
local: 'transform',
value: transform
});
path = applyTransforms(pathElem, pathElem.pathJS, true, params.floatPrecision);
// transformed data rounding
path.forEach(function(pathItem) {
if (pathItem.data) {
pathItem.data = pathItem.data.map(function(num) {
return +num.toFixed(params.floatPrecision);
});
}
});
// save new
js2path(pathElem, path, params);
}
}
});
return data;
};