diff options
Diffstat (limited to 'node_modules/svgo/plugins/transformsWithOnePath.js')
| -rw-r--r-- | node_modules/svgo/plugins/transformsWithOnePath.js | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/node_modules/svgo/plugins/transformsWithOnePath.js b/node_modules/svgo/plugins/transformsWithOnePath.js new file mode 100644 index 00000000..f4dec7e6 --- /dev/null +++ b/node_modules/svgo/plugins/transformsWithOnePath.js @@ -0,0 +1,327 @@ +'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; + +}; |
