UNPKG

@jscad/modeling

Version:

Constructive Solid Geometry (CSG) Library for JSCAD

93 lines (89 loc) 3.29 kB
const vectorChar = require('./vectorChar') const vectorParams = require('./vectorParams') // translate text line const translateLine = (options, line) => { const { x, y } = Object.assign({ x: 0, y: 0 }, options || {}) const segments = line.segments let segment = null let point = null for (let i = 0, il = segments.length; i < il; i++) { segment = segments[i] for (let j = 0, jl = segment.length; j < jl; j++) { point = segment[j] segment[j] = [point[0] + x, point[1] + y] } } return line } /** * Construct an array of character segments from a ascii string whose characters code is between 31 and 127, * if one character is not supported it is replaced by a question mark. * @param {Object|String} [options] - options for construction or ascii string * @param {Float} [options.xOffset=0] - x offset * @param {Float} [options.yOffset=0] - y offset * @param {Float} [options.height=21] - font size (uppercase height) * @param {Float} [options.lineSpacing=1.4] - line spacing expressed as a percentage of font size * @param {Float} [options.letterSpacing=1] - extra letter spacing expressed as a percentage of font size * @param {String} [options.align='left'] - multi-line text alignment: left, center, right * @param {Float} [options.extrudeOffset=0] - width of the extrusion that will be applied (manually) after the creation of the character * @param {String} [options.input='?'] - ascii string (ignored/overwrited if provided as seconds parameter) * @param {String} [text='?'] - ascii string * @returns {Array} characters segments [[[x, y], ...], ...] * @alias module:modeling/text.vectorText * * @example * let textSegments = vectorText() * let textSegments = vectorText('OpenJSCAD') * let textSegments = vectorText({ yOffset: -50 }, 'OpenJSCAD') * let textSegments = vectorText({ yOffset: -80, input: 'OpenJSCAD' }) */ const vectorText = (options, text) => { const { xOffset, yOffset, input, font, height, align, extrudeOffset, lineSpacing, letterSpacing } = vectorParams(options, text) let [x, y] = [xOffset, yOffset] let i, il, char, vect, width, diff let line = { width: 0, segments: [] } const lines = [] let output = [] let maxWidth = 0 const lineStart = x const pushLine = () => { lines.push(line) maxWidth = Math.max(maxWidth, line.width) line = { width: 0, segments: [] } } for (i = 0, il = input.length; i < il; i++) { char = input[i] vect = vectorChar({ xOffset: x, yOffset: y, font, height, extrudeOffset }, char) if (char === '\n') { x = lineStart y -= vect.height * lineSpacing pushLine() continue } width = vect.width * letterSpacing line.width += width x += width if (char !== ' ') { line.segments = line.segments.concat(vect.segments) } } if (line.segments.length) { pushLine() } for (i = 0, il = lines.length; i < il; i++) { line = lines[i] if (maxWidth > line.width) { diff = maxWidth - line.width if (align === 'right') { line = translateLine({ x: diff }, line) } else if (align === 'center') { line = translateLine({ x: diff / 2 }, line) } } output = output.concat(line.segments) } return output } module.exports = vectorText