mirror of
https://github.com/Blockzilla101/citation.git
synced 2025-04-16 09:34:42 -04:00
fix #4
This commit is contained in:
parent
0b3fef0fe4
commit
93abcdc48e
5 changed files with 326 additions and 1152 deletions
4
index.js
4
index.js
|
@ -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
1346
package-lock.json
generated
File diff suppressed because it is too large
Load diff
25
package.json
25
package.json
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
82
src/util.js
82
src/util.js
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue