Doodle3D-Core/src/utils/textUtils.js

59 lines
1.8 KiB
JavaScript
Raw Normal View History

2017-10-25 11:39:02 +02:00
import { SHAPE_CACHE_LIMIT } from '../constants/general.js';
import { Text } from '@doodle3d/cal';
import { POTRACE_OPTIONS } from '../constants/d2Constants.js';
import * as POTRACE from '@doodle3d/potrace-js';
import ClipperShape from '@doodle3d/clipper-js';
import { shapeToVectorShape } from './vectorUtils.js';
import memoize from 'memoizee';
const MARGIN = 200;
export const createText = memoize(createTextRaw, { max: SHAPE_CACHE_LIMIT });
export function createTextRaw(text, size, family, style, weight) {
if (text === '') return [];
const { width, height, canvas } = createTextCanvas(text, size, family, style, weight);
// TODO merge with potrace in flood fill trace reducer
const paths = POTRACE.getPaths(POTRACE.traceCanvas(canvas, POTRACE_OPTIONS));
const halfWidth = width / 2;
const halfHeight = height / 2;
const pathsOffset = paths.map(path => path.map(({ x, y }) => ({
x: (x - halfWidth) / 10,
y: (y - halfHeight) / 10
})));
const shapes = new ClipperShape(pathsOffset, true, true, false)
.fixOrientation()
.seperateShapes()
.map(shape => shape.mapToLower())
.map(shapeToVectorShape);
return shapes;
}
const textContext = new Text();
export function createTextCanvas(text, size, family, style, weight) {
textContext.size = size;
textContext.family = family;
textContext.style = style;
textContext.weight = weight;
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const width = Math.ceil(textContext.measure(context, text)) + 2 * MARGIN;
const height = size + 2 * MARGIN;
canvas.width = width;
canvas.height = height;
context.fillStyle = 'white';
context.fillRect(0, 0, width, height);
textContext.drawText(context, text, MARGIN, height / 2);
return { width, height, canvas };
}