diff --git a/package-lock.json b/package-lock.json index 4f656f570..13068118b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -86,7 +86,6 @@ "skia-canvas": "^3.0.8", "tailwindcss": "^4.2.4", "tsconfig-paths": "^4.2.0", - "twemoji-colr-font": "^15.0.3", "typescript": "^6.0.3", "typescript-eslint": "^8.59.1", "vite": "^8.0.10", @@ -10360,13 +10359,6 @@ "fsevents": "~2.3.3" } }, - "node_modules/twemoji-colr-font": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/twemoji-colr-font/-/twemoji-colr-font-15.0.3.tgz", - "integrity": "sha512-UsK4JUpaczeVoMGeYMnKaMTxKt7fujg1nQOk4NaC0teZmdOo+uAai0DIuaSzsMkShtG4J75F0OEsVdGJ+Q1pHQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index d7837534e..42b60ef01 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "skia-canvas": "^3.0.8", "tailwindcss": "^4.2.4", "tsconfig-paths": "^4.2.0", - "twemoji-colr-font": "^15.0.3", "typescript": "^6.0.3", "typescript-eslint": "^8.59.1", "vite": "^8.0.10", diff --git a/resources/fonts/twemoji-colr-OFL.txt b/resources/fonts/twemoji-colr-OFL.txt new file mode 100644 index 000000000..787fc8ffd --- /dev/null +++ b/resources/fonts/twemoji-colr-OFL.txt @@ -0,0 +1,121 @@ +# License for the font file + +SIL OPEN FONT LICENSE +Version 1.1 - 26 February 2007 + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting — in part or in whole — any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +# License for the Visual Design + +The emoji art comes from [Twemoji](https://twitter.github.io/twemoji), +and is used and redistributed under the CC-BY-4.0 [license terms](https://github.com/twitter/twemoji#license) +offered by the Twemoji project. + +### Creative Commons Attribution 4.0 International (CC BY 4.0) +https://creativecommons.org/licenses/by/4.0/legalcode +or for the human readable summary: https://creativecommons.org/licenses/by/4.0/ + + +#### You are free to: +**Share** — copy and redistribute the material in any medium or format + +**Adapt** — remix, transform, and build upon the material for any purpose, even commercially. + +The licensor cannot revoke these freedoms as long as you follow the license terms. + + +#### Under the following terms: +**Attribution** — You must give appropriate credit, provide a link to the license, +and indicate if changes were made. +You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. + +**No additional restrictions** — You may not apply legal terms or **technological measures** +that legally restrict others from doing anything the license permits. + +#### Notices: +You do not have to comply with the license for elements of the material in the public domain +or where your use is permitted by an applicable exception or limitation. No warranties are given. +The license may not give you all of the permissions necessary for your intended use. +For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. + diff --git a/resources/fonts/twemoji-colr.woff2 b/resources/fonts/twemoji-colr.woff2 new file mode 100644 index 000000000..6cc58b6aa Binary files /dev/null and b/resources/fonts/twemoji-colr.woff2 differ diff --git a/scripts/build-namelayer-assets.mjs b/scripts/build-namelayer-assets.mjs index 5f99ccb85..a0110149e 100644 --- a/scripts/build-namelayer-assets.mjs +++ b/scripts/build-namelayer-assets.mjs @@ -14,7 +14,7 @@ const fontPng = "namelayer_overpass.png"; const fontXml = "namelayer_overpass.xml"; const fontFace = "namelayer_overpass"; const emojiFontFamily = "NameLayerEmoji"; -const emojiFontPath = require.resolve("twemoji-colr-font/twemoji.woff2"); +const emojiFontPath = path.join(fontsDir, "twemoji-colr.woff2"); const emojiFontSize = 96; const atlasFramePaddingRatio = 1 / 16; const colorDetectionThreshold = 12; @@ -52,6 +52,7 @@ const iconSources = [ fs.mkdirSync(fontsDir, { recursive: true }); fs.mkdirSync(imagesDir, { recursive: true }); +const overpassFontPath = findFontSource(); FontLibrary.use(emojiFontFamily, [emojiFontPath]); await buildMsdfFont(); @@ -59,11 +60,7 @@ await buildIconAtlas(); await buildEmojiAtlas(); async function buildMsdfFont() { - const fontPath = fontSourceCandidates - .map((fileName) => path.join(fontsDir, fileName)) - .find((candidate) => fs.existsSync(candidate)); - - if (!fontPath) { + if (!overpassFontPath) { const fallbackXml = fs .readFileSync(path.join(fontsDir, "round_6x6_modified.xml"), "utf8") .replace(/face="round_6x6_modified"/g, `face="${fontFace}"`) @@ -79,7 +76,7 @@ async function buildMsdfFont() { const generateBMFont = require("msdf-bmfont-xml"); const { textures, font } = await new Promise((resolve, reject) => { generateBMFont( - fontPath, + overpassFontPath, { filename: path.join(fontsDir, path.basename(fontPng, ".png")), outputType: "xml", @@ -216,10 +213,7 @@ async function buildEmojiAtlas() { const x = col * cell; const y = row * cell; drawPackedAtlasFrame(ctx, x, y, cell, (scratchCtx, scratchSize) => { - scratchCtx.textAlign = "center"; - scratchCtx.textBaseline = "middle"; - scratchCtx.font = `${emojiFontSize}px ${emojiFontFamily}`; - scratchCtx.fillText(emoji, scratchSize / 2, scratchSize / 2); + drawEmojiText(scratchCtx, scratchSize, emoji); }); frames[emoji] = { frame: { x, y, w: cell, h: cell }, @@ -258,6 +252,13 @@ async function buildEmojiAtlas() { ); } +function drawEmojiText(ctx, size, emoji) { + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.font = `${emojiFontSize}px ${emojiFontFamily}`; + ctx.fillText(emoji, size / 2, size / 2); +} + function drawPackedAtlasFrame(targetCtx, x, y, cell, drawSource) { const scratchSize = cell * 2; const scratch = new Canvas(scratchSize, scratchSize); @@ -389,3 +390,9 @@ function readEmojiTable() { return Array.from(match[1].matchAll(/"([^"]+)"/g), (match) => match[1]); } + +function findFontSource() { + return fontSourceCandidates + .map((fileName) => path.join(fontsDir, fileName)) + .find((candidate) => fs.existsSync(candidate)); +}