UNPKG

ultimate-text-to-image

Version:

Generate UTF8 texts into image with auto line break for all international language, including Chinese, Japanese, Korean, etc..

173 lines (172 loc) 7.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UltimateTextToImage = void 0; const canvas_1 = require("canvas"); const BaseClass_1 = require("./BaseClass"); const Measurable_1 = require("./Measurable"); const canvas_2 = require("./utils/canvas"); class UltimateTextToImage extends BaseClass_1.BaseClass { constructor(text, options = {}, renderOptions = {}) { super(); this.text = text; this.options = options; this.renderOptions = renderOptions; this._defaultOptions = { width: undefined, height: undefined, maxWidth: undefined, maxHeight: undefined, noAutoWrap: false, fontFamily: "Arial", fontWeight: false, fontStyle: false, fontSize: 24, minFontSize: undefined, fontColor: "#333333", strokeSize: 0, strokeColor: "#000000", lineHeight: undefined, lineHeightMultiplier: undefined, autoWrapLineHeight: undefined, autoWrapLineHeightMultiplier: undefined, margin: 0, marginLeft: undefined, marginTop: undefined, marginRight: undefined, marginBottom: undefined, useGlyphPadding: true, chopOverflow: false, align: "left", valign: "top", alignToCenterIfHeightLE: 0, alignToCenterIfLinesLE: 0, borderColor: "#000000", borderSize: 0, backgroundColor: "", underlineSize: 0, underlineColor: "", images: [], nestedAlign: undefined, nestedValign: undefined, }; } get measuredParagraph() { this._checkHasRendered(); return this._measuredParagraph; } render() { this._startTimer(); this._createCanvas(); this._endTimer(); return this; } // draw the image based on various options _createCanvas() { const text = this.text; // merge default options const options = Object.assign({}, this._defaultOptions, this.options); // prepare all variables const { height, width, noAutoWrap, fontFamily, fontStyle, fontWeight, fontSize, chopOverflow, useGlyphPadding, underlineSize, underlineColor, images, } = options; let { maxWidth, maxHeight, minFontSize } = options; // work on default values maxHeight = typeof maxHeight === "number" ? maxHeight : (typeof height === "number" ? height : UltimateTextToImage.maxSize); maxWidth = typeof maxWidth === "number" ? maxWidth : (typeof width === "number" ? width : UltimateTextToImage.maxSize); // update max size maxWidth = Math.max(width || 1, maxWidth); maxHeight = Math.max(height || 1, maxHeight); minFontSize = typeof minFontSize === "number" ? minFontSize : options.fontSize; const marginLeft = typeof options.marginLeft === "number" ? options.marginLeft : options.margin; const marginTop = typeof options.marginTop === "number" ? options.marginTop : options.margin; const marginRight = typeof options.marginRight === "number" ? options.marginRight : options.margin; const marginBottom = typeof options.marginBottom === "number" ? options.marginBottom : options.margin; // find the best measured paragraph const measuredParagraph = UltimateTextToImage.measurable.getMeasuredParagraph({ text, maxWidth: maxWidth - marginLeft - marginRight, maxHeight: maxHeight - marginTop - marginBottom, noAutoWrap, fontFamily, fontStyle, fontWeight, maxFontSize: fontSize, minFontSize, fontSize, useGlyphPadding, lineHeight: options.lineHeight, lineHeightMultiplier: options.lineHeightMultiplier, autoWrapLineHeight: options.autoWrapLineHeight, autoWrapLineHeightMultiplier: options.autoWrapLineHeightMultiplier, }); // prepared update varaibles const finalFontSize = measuredParagraph.fontSize; // update the alignments let finalValign = options.valign; let finalAlign = options.align; const desiredCanvasHeight = measuredParagraph.height + marginTop + marginBottom; const desiredCanvasBoundingHeight = measuredParagraph.boundingHeight + marginTop + marginBottom; const desiredCanvasWidth = measuredParagraph.width + marginLeft + marginRight; const desiredCanvasBoundingWidth = measuredParagraph.boundingWidth + marginLeft + marginRight; let finalHeight = Math.max(typeof height === "number" ? height : desiredCanvasHeight, Math.min(maxHeight, desiredCanvasHeight)); let finalWidth = Math.max(typeof width === "number" ? width : desiredCanvasWidth, Math.min(maxWidth, desiredCanvasWidth)); if (options.alignToCenterIfHeightLE && measuredParagraph.height <= options.alignToCenterIfHeightLE) { finalValign = "middle"; finalAlign = "center"; } if (options.alignToCenterIfLinesLE && measuredParagraph.measuredLines.length <= options.alignToCenterIfLinesLE) { finalValign = "middle"; finalAlign = "center"; } // if we want more precise spacing if (useGlyphPadding) { finalHeight = Math.max(typeof height === "number" ? height : desiredCanvasBoundingHeight, Math.min(maxHeight, desiredCanvasBoundingHeight)); finalWidth = Math.max(typeof width === "number" ? width : desiredCanvasBoundingWidth, Math.min(maxWidth, desiredCanvasBoundingWidth)); } // update the object values finalWidth = Math.max(1, finalWidth); finalHeight = Math.max(1, finalHeight); this._measuredParagraph = measuredParagraph; this._canvas = (0, canvas_1.createCanvas)(finalWidth, finalHeight); const ctx = this._canvas.getContext("2d"); // hook (0, canvas_2.renderHook)(this._canvas, this.renderOptions.preRender); // draw images (0, canvas_2.drawImages)(ctx, { width: finalWidth, height: finalHeight, layer: -1, images }); // draw background (0, canvas_2.drawBackgroundColor)(ctx, { color: options.backgroundColor }); // draw border (0, canvas_2.drawBorder)(ctx, { color: options.borderColor, size: options.borderSize }); // draw images (0, canvas_2.drawImages)(ctx, { width: finalWidth, height: finalHeight, layer: 0, images }); // draw texts (0, canvas_2.drawTexts)(ctx, { measuredParagraph, width: finalWidth, height: finalHeight, fontFamily, fontStyle: options.fontStyle, fontWeight: options.fontWeight, fontSize: finalFontSize, fontColor: options.fontColor, strokeSize: options.strokeSize, strokeColor: options.strokeColor, valign: finalValign, align: finalAlign, // margin: options.margin, marginLeft, marginTop, marginRight, marginBottom, chopOverflow, useGlyphPadding, underlineSize, underlineColor, }); (0, canvas_2.drawImages)(ctx, { width: finalWidth, height: finalHeight, layer: 1, images }); // hook (0, canvas_2.renderHook)(this._canvas, this.renderOptions.posRender); return this._canvas; } } exports.UltimateTextToImage = UltimateTextToImage; UltimateTextToImage.measurable = new Measurable_1.Measurable(); UltimateTextToImage.maxSize = 2 << 14 - 1;