This commit is contained in:
Blockzilla101 2023-02-06 19:58:25 +05:00
parent 0b3fef0fe4
commit 93abcdc48e
5 changed files with 326 additions and 1152 deletions

View file

@ -1,5 +1,5 @@
const { Citation } = require('./src/citation')
const { registerFont } = require('canvas')
const { GlobalFonts } = require('@napi-rs/canvas')
const path = require('path')
const fs = require('fs')
@ -11,6 +11,6 @@ if (!fs.existsSync(dataDir)) throw new Error(`${dataDir} is no where to be found
if (!fs.existsSync(fontFile)) throw new Error(`Font ${fontFile} is no where to be found`)
if (!fs.existsSync(logo)) throw new Error(`Logo ${logo} is no where to be found`)
registerFont(fontFile, { family: 'BMmini' });
GlobalFonts.registerFromPath(path.join(__dirname, 'data', 'BMmini.ttf'), 'BMmini')
module.exports = { Citation }

1346
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,15 @@
{
"name": "@blockzilla101/citation",
"version": "1.2.3",
"dependencies": {
"canvas": "^2.6.1",
"gif-encoder-2": "^1.0.5"
},
"author": "Blockzilla101",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/Blockzilla101/citation"
}
"name": "@blockzilla101/citation",
"version": "1.2.3",
"dependencies": {
"@napi-rs/canvas": "^0.1.34",
"args-parser": "^1.3.0",
"gif-encoder-2": "^1.0.5"
},
"author": "Blockzilla101",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/Blockzilla101/citation"
}
}

View file

@ -1,4 +1,5 @@
const { createCanvas, Canvas, loadImage, Image } = require('canvas');
// const { createCanvas, Canvas, loadImage, Image } = require('canvas');
const { createCanvas, loadImage, Image, Canvas } = require('@napi-rs/canvas')
const { text, textWrapped, line, dottedLine, barcode, rect, textFitsHeight, wrap, tint } = require('./util');
const Encoder = require('gif-encoder-2');
const fs = require('fs');
@ -146,9 +147,6 @@ module.exports.Citation = class {
this.#canvas = createCanvas(this.#width, this.#height);
this.#ctx = this.#canvas.getContext('2d');
this.#ctx.imageSmoothingEnabled = false;
this.#ctx.antialias = 'none';
if (!this.#logo) this.#logo = await loadImage(`${__dirname + '/../data'}/logo.png`);
}
@ -161,7 +159,8 @@ module.exports.Citation = class {
*/
async render(out, gif = false, frameRate = 10, yPos = null) {
await this.#draw()
let data = gif ? await this.#animated(frameRate, yPos) : this.#canvas.toBuffer()
const b = this.#canvas.toBuffer('image/png');
let data = gif ? await this.#animated(frameRate, yPos) : b
if (out) {
fs.writeFileSync(out, data)
}
@ -174,19 +173,19 @@ module.exports.Citation = class {
if (this.resizeReason) {
let wrapped = wrap(this.reason, this.font, this.moaFt, this.#ctx, this.#reasonMaxWidth)
const ogHeight = this.#height
let newHeight = this.#height;
if (!textFitsHeight(wrapped, this.font, this.#ctx, this.#reasonMaxHeight)) {
this.#ctx.font = this.font
let metrics = this.#ctx.measureText(wrapped);
this.#canvas.height += (metrics.emHeightDescent - (metrics.emHeightAscent / 2)) - this.#reasonMaxHeight;
this.#height = this.#canvas.height
newHeight += (metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent + 2) * wrapped.split('\n').length - this.#reasonMaxHeight;
if (this.resizeLimit > ogHeight) {
if (this.#height > this.resizeLimit) {
this.#canvas.height = this.resizeLimit
this.#height = this.resizeLimit
if (newHeight > this.resizeLimit) {
newHeight = this.resizeLimit
}
}
}
this.height = this.#canvas.height
this.#height = newHeight
await this.#createCanvas()
}
// Bg

View file

@ -1,6 +1,6 @@
const { NodeCanvasRenderingContext2D, createCanvas } = require('canvas');
const { createCanvas, SKRSContext2D } = require('@napi-rs/canvas');
/** @typedef {NodeCanvasRenderingContext2D} RenderingContext*/
/** @typedef {SKRSContext2D} RenderingContext*/
/** @typedef {string|CanvasGradient|CanvasPattern} Style*/
/** @typedef {"center"|"end"|"left"|"right"|"start"} TextAlignment*/
@ -44,7 +44,7 @@ function line(startX, startY,endX, endY, style , ctx, width = 1) {
}
/**
* @param {string} text
* @param {string} fillText
* @param {number} x
* @param {number} y
* @param {string} font
@ -53,24 +53,27 @@ function line(startX, startY,endX, endY, style , ctx, width = 1) {
* @param {TextAlignment} [alignment="left"]
* @param {number} [maxWidth=0]
*/
function text(text, x, y, font, style, ctx, alignment = 'left', maxWidth) {
function text(fillText, x, y, font, style, ctx, alignment = 'left', maxWidth) {
if (fillText.includes('\n')) {
const metrics = ctx.measureText(fillText)
const height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent + 2
let currY = y;
const lines = fillText.split('\n')
for (const line of lines) {
text(line, x, currY, font, style, ctx, alignment, maxWidth)
currY += height
}
return
}
ctx.fillStyle = style
ctx.strokeStyle = style
ctx.font = font;
ctx.textAlign = alignment
if (typeof maxWidth !== 'undefined') {
const metrics = ctx.measureText(text);
const size = metrics.emHeightAscent + metrics.emHeightDescent;
if (maxWidth < 0) maxWidth = 0;
let width = ctx.measureText(text).width;
while(width > maxWidth) {
if (width - maxWidth > maxWidth) text = text.substr(0, text.length - (width / size));
text = text.substr(0, text.length - 1);
width = ctx.measureText(text).width
}
}
ctx.fillText(text, x, y);
ctx.fillText(fillText, x, y, maxWidth);
}
/**
@ -86,40 +89,31 @@ function text(text, x, y, font, style, ctx, alignment = 'left', maxWidth) {
*/
function textWrapped(str, x, y, font, style, ctx, maxWidth, maxHeight, alignment = "left") {
let newStr = wrap(str, font, style, ctx, maxWidth)
if (typeof maxHeight !== 'undefined' && maxHeight > 0 && newStr.includes('\n')) {
let metrics = ctx.measureText(newStr);
let height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
while (height > maxHeight) {
newStr = newStr.substr(0, newStr.lastIndexOf('\n'));
metrics = ctx.measureText(newStr);
height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
}
}
text(newStr, x, y, font, style, ctx, alignment, maxWidth);
}
function wrap(str, font, style, ctx, maxWidth) {
let words = str.split(" ");
let lines = [];
let currentLine = words[0];
ctx.font = font;
ctx.style = style;
ctx.fillStyle = style
for (let i = 1; i < words.length; i++) {
let word = words[i];
let width = ctx.measureText(currentLine + " " + word).width;
if (width < maxWidth) {
currentLine += " " + word;
} else {
lines.push(currentLine);
currentLine = word;
const lines = str.split('\n')
const newStr = []
for (const line of lines) {
const words = line.split(' ');
let currStr = []
for (const word of words) {
currStr.push(word)
if (ctx.measureText(currStr.join(' ')).width > maxWidth) {
const lastWord = currStr.pop()
newStr.push(currStr.join(' '))
currStr = []
currStr.push(lastWord)
}
}
newStr.push(currStr.join(' ').trim())
}
lines.push(currentLine);
return lines.join('\n');
return newStr.join('\n').trim()
}
/**
@ -173,7 +167,7 @@ function textFitsWidth(text, font, ctx, maxWidth) {
function textFitsHeight(text, font, ctx, maxHeight) {
ctx.font = font;
let metrics = ctx.measureText(text);
return metrics.emHeightDescent - (metrics.emHeightAscent / 2) <= maxHeight;
return (metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent + 2) * text.split('\n').length <= maxHeight;
}
function tint(image, color, opacity = 0.5) {