UNPKG

orthomoji

Version:

Create text art with emojis!

154 lines (135 loc) 5 kB
import { drawBorderToCanvas } from './../tools/border.js'; import pkg from 'node-canvas-with-twemoji'; const { fillTextWithTwemoji } = pkg; /** * Number of characters per row/column in a letter */ const BITS_PER_CHAR = 5; /** * Gets the width of a letter * * @param {number} fontSize - Size of character (not letter) * @returns {number} Calculated width */ const getWidthPerLetter = fontSize => fontSize * BITS_PER_CHAR; /** * Gets the height of a letter * * @param {number} fontSize - Size of character (not letter) * @returns {number} Calculated height */ const getHeightPerLetter = fontSize => fontSize * BITS_PER_CHAR; /** * Gets the padding width of the canvas * * @param {number} fontSize - Size of character (not letter) * @returns {number} Calculated width */ const getPaddingWidth = fontSize => fontSize * 2; /** * Gets the padding height of the canvas * * @param {number} fontSize - Size of character (not letter) * @returns {number} Calculated height */ const getPaddingHeight = fontSize => fontSize * 2; /** * Gets the amount of pixels that a border added to the padding * * @param {object} borderStyle - Border object that contains border parameters * @returns {number} - Width of the border in px */ const getAddedBorderWidth = borderStyle => { return (borderStyle.width !== undefined) ? borderStyle.width : 0; } /** * Changes the background style/colour of a canvas * * @param {HTMLCanvasElement} canvas - Canvas to change BG colour of * @param {string} style - Valid CSS colour * @returns {HTMLCanvasElement} Newly edited canvas element */ const changeBGCanvas = (canvas, style) => { try { canvas.getContext('2d').fillStyle = style; canvas.getContext('2d').fillRect(0, 0, canvas.width, canvas.height); return canvas; } catch (e) { throw new Error(`${style} is not a correct style for the background`); } }; /** * Resizes a canvas to properly apply text and changes the background style if needed * * @param {HTMLCanvasElement} canvas - Canvas that we will resize * @param {string} str - String we will print to canvas. * @returns {HTMLCanvasElement} Newly resized canvas */ const editCanvas = (canvas, str, fontSize, style, borderStyle) => { const longestLine = str.split('\n').sort((a, b) => b.length - a.length)[0]; const lines = (str.match(/\n/g) || []).length + 1; // Add padding on both L and R sides, then add space for each letter being typed canvas.width = (getPaddingWidth(fontSize) * 2) + (longestLine.length * getWidthPerLetter(fontSize)) + (getAddedBorderWidth(borderStyle) * 2); // Add padding for both up and down, then add space for each letter being typed const height = (getPaddingHeight(fontSize)) + (lines * getHeightPerLetter(fontSize)) + (getAddedBorderWidth(borderStyle) * 2); canvas.height = (lines > 1) ? height + (fontSize * (lines - 1)) : height; // Change background style, if present const newCanvas = (style !== null) ? changeBGCanvas(canvas, style) : canvas; return drawBorderToCanvas(newCanvas, borderStyle); }; /** * Adds a string of text to a canvas * * @param {HTMLCanvasElement} canvas - Canvas we will apply text to * @param {string} str - String we will apply to canvas * @param {JSON} fontSet - JSON object containing the font set * @param {number} fontSize - Size of the font to print * @param {string} bgStyle - Background style of the canvas * @param {JSON} borderStyle - Object that determines how to style a border * @returns {HTMLCanvasElement} Canvas with text drawn to it */ const addTextToCanvas = async (canvas, str, fontSet, fontSize, bgStyle, borderStyle) => { let editedCanvas = editCanvas( canvas, str, fontSize, bgStyle, borderStyle ); const ctx = editedCanvas.getContext('2d'); ctx.font = `${fontSize}px serif`; // Set the starting point const getNewStartX = (getPaddingWidth(fontSize) / 1.5) + getAddedBorderWidth(borderStyle); let currentX = getNewStartX; let currentY = (getPaddingHeight(fontSize) + getAddedBorderWidth(borderStyle)); // Draw each row of a letter then adds spacing or a newline for (const c of str) { const spacing = (fontSize * BITS_PER_CHAR); let topX = currentX; let topY = currentY; if (c !== '\n') { const fontBits = fontSet[c]; for (const elem of fontBits) { currentX += fontSize; if (elem === '') { currentX = topX; currentY += fontSize; } await fillTextWithTwemoji(ctx, elem, currentX, currentY); }; currentY = topY; currentX = topX + spacing; } else { currentY = topY + spacing + fontSize; currentX = getNewStartX; } } return editedCanvas; }; export { addTextToCanvas };