gerber-to-svg
Version:
Render individual Gerber / NC drill files as SVGs
187 lines (150 loc) • 4.2 kB
JavaScript
// reduce a shape array into a string to place is defs
var util = require('./_util')
var shift = util.shift
var createMask = util.createMask
var maskLayer = util.maskLayer
var element = function(tag, attr, children) {
return {tag: tag, attr: attr, children: children || []}
}
var circle = function(cx, cy, r, width) {
var attr = {
cx: shift(cx),
cy: shift(cy),
r: shift(r),
}
if (width != null) {
attr['stroke-width'] = shift(width)
attr.fill = 'none'
}
return element('circle', attr)
}
var rect = function(cx, cy, r, width, height) {
var attr = {
x: shift(cx - width / 2),
y: shift(cy - height / 2),
width: shift(width),
height: shift(height),
}
if (r) {
attr.rx = shift(r)
attr.ry = shift(r)
}
return element('rect', attr)
}
var poly = function(points) {
var pointsAttr = points
.map(function(point) {
return point.map(shift).join(',')
})
.join(' ')
return element('polygon', {points: pointsAttr})
}
var clip = function(maskIdPrefix, index, shapes, ring, createElement) {
var maskId = maskIdPrefix + 'mask-' + index
var maskUrl = 'url(#' + maskId + ')'
var circleNode = circle(ring.cx, ring.cy, ring.r, ring.width)
var mask = createElement('mask', {id: maskId, stroke: '#fff'}, [
createElement(circleNode.tag, circleNode.attr),
])
var groupChildren = shapes.map(function(shape) {
var node =
shape.type === 'rect'
? rect(shape.cx, shape.cy, shape.r, shape.width, shape.height)
: poly(shape.points)
return createElement(node.tag, node.attr)
})
var layer = element('g', {mask: maskUrl}, groupChildren)
return {mask: mask, layer: layer}
}
module.exports = function reduceShapeArray(
prefix,
code,
shapeArray,
createElement
) {
var id = prefix + '_pad-' + code
var maskIdPrefix = id + '_'
var image = shapeArray.reduce(
function(result, shape, index) {
var svg
switch (shape.type) {
case 'circle':
svg = circle(shape.cx, shape.cy, shape.r)
break
case 'ring':
svg = circle(shape.cx, shape.cy, shape.r, shape.width)
break
case 'rect':
svg = rect(shape.cx, shape.cy, shape.r, shape.width, shape.height)
break
case 'poly':
svg = poly(shape.points)
break
case 'clip':
var clipNodes = clip(
maskIdPrefix,
index,
shape.shape,
shape.clip,
createElement
)
result.masks.push(clipNodes.mask)
svg = clipNodes.layer
break
case 'layer':
result.count++
result.last = shape.polarity
// if the polarity is clear, wrap the group and start a mask
if (shape.polarity === 'clear') {
var nextMaskId = maskIdPrefix + result.count
result.maskId = nextMaskId
result.maskBox = shape.box.slice(0)
result.maskChildren = []
result.layers = [
maskLayer(nextMaskId, result.layers, createElement),
]
} else {
var mask = createMask(
result.maskId,
result.maskBox,
result.maskChildren,
createElement
)
result.masks.push(mask)
}
break
}
if (svg) {
if (shapeArray.length === 1) {
svg.attr.id = id
}
var svgElement = createElement(svg.tag, svg.attr, svg.children)
if (result.last === 'dark') {
result.layers.push(svgElement)
} else {
result.maskChildren.push(svgElement)
}
}
return result
},
{
count: 0,
last: 'dark',
layers: [],
maskId: '',
maskBox: [],
maskChildren: [],
masks: [],
}
)
if (image.last === 'clear') {
image.masks.push(
createMask(image.maskId, image.maskBox, image.maskChildren, createElement)
)
}
if (shapeArray.length > 1) {
image.layers = createElement('g', {id: id}, image.layers)
}
return image.masks.concat(image.layers)
}