add font support

main
Mari 2 weeks ago
parent 7abab6a001
commit 7891fce774
  1. 5
      .gitignore
  2. 2
      Dockerfile
  3. 3
      src/commands/base.ts
  4. 4
      src/commands/party.ts
  5. 5
      src/index.ts
  6. 9
      src/renderStatus.ts

5
.gitignore vendored

@ -13,6 +13,7 @@ logs/
!.vscode/extensions.json
.env
dist/
data/characters
data/images
data/characters/
data/images/
data/party.yaml
data/fonts/

@ -1,5 +1,5 @@
FROM node:latest AS build
RUN apt-get update && apt-get install -y --no-install-recommends dumb-init
RUN apt-get update && apt-get install -y --no-install-recommends dumb-init fira-
WORKDIR /usr/src/app
COPY package*.json .prettierrc .eslintrc.cjs tsconfig.json /usr/src/app/
COPY src /usr/src/app/src/

@ -267,7 +267,8 @@ export abstract class AbstractCharacterStatusCommand extends SlashCommand {
.slice(0, 10)
.map((s) => characterDataDelta(s, this.dataDir))
);
const images = await Promise.all(deltas.map(async (s) => renderStatus(await svg, s)));
const fontDir = join(this.dataDir, 'fonts')
const images = await Promise.all(deltas.map(async (s) => renderStatus(await svg, s, fontDir)));
const sharps = images.map((b) => Sharp(b));
const metadatas = await Promise.all(sharps.map((s) => s.metadata()));
let resultImage: Buffer | null;

@ -46,7 +46,7 @@ export class PartyCommand extends AbstractCharacterStatusCommand {
> {
const replace: boolean | undefined = ctx.options.replace;
const oldPartyMemberNames = party.activeParty;
const newPartyMemberData = characters.get('party');
const newPartyMemberData = characters.get('characters');
if (!newPartyMemberData || newPartyMemberData.length === 0) {
return [
`The current active party is:\n **${oldPartyMemberNames.join('**\n **')}**`,
@ -78,7 +78,7 @@ export class PartyCommand extends AbstractCharacterStatusCommand {
];
if (replace || deltas.length === 0 || (replace === false && deltas.length > newPartyMemberNames.length)) {
return [
`The current active party is:\n **${newPartyMemberData.map((c) => c.name).join('**\n **')}**`,
`The active party is now:\n **${newPartyMemberData.map((c) => c.name).join('**\n **')}**`,
newPartyMemberData.flatMap((c) => (c.success ? [c] : []))
];
} else {

@ -37,7 +37,10 @@ const server = fastify({
logger: true
});
const options = { dataDir: process.env.DATA_DIR ?? '../data' };
const options = {
dataDir: process.env.DATA_DIR ?? '../data',
fontDir: process.env.FONT_DIR ?? '../fonts'
};
creator
.withServer(new FastifyServer(server))

@ -169,7 +169,7 @@ const mappings: [filter: (status: GameStatus) => boolean, selector: string, hit:
[dead(), '#characterFaceImage', removeElement]
];
export async function renderStatus(svgTemplate: string, status: GameStatusWithPortrait): Promise<Buffer> {
export async function renderStatus(svgTemplate: string, status: GameStatusWithPortrait, fontDir: string): Promise<Buffer> {
const dom = new JSDOM(svgTemplate, {
contentType: 'image/svg+xml',
pretendToBeVisual: false,
@ -183,7 +183,12 @@ export async function renderStatus(svgTemplate: string, status: GameStatusWithPo
}
}
}
const resvg = new Resvg(dom.window.document.documentElement.outerHTML, {});
const resvg = new Resvg(dom.window.document.documentElement.outerHTML, {
font: {
fontDirs: [fontDir],
loadSystemFonts: false,
}
});
resvg.resolveImage('https://invalid.invalid/face.png', status.portrait);
return resvg.render().asPng();
}

Loading…
Cancel
Save