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
JavaScript
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;
;