Skip to content

Commit

Permalink
fix: artifacts in italic font
Browse files Browse the repository at this point in the history
  • Loading branch information
jejebecarte committed Sep 27, 2024
1 parent 9dbb407 commit 996da9e
Show file tree
Hide file tree
Showing 12 changed files with 674,062 additions and 544,332 deletions.
12 changes: 7 additions & 5 deletions scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ Minecraft only stores the regular version of its font in its assets, utilising t

- `Bold:` The character is drawn a second time over the original, this time one pixel to the right.

- `Italic:` The character's resolution is tripled (e.g. a character that is normally `12x9` becomes `36x27`). The bottom row of pixels stay fixed, while every set of 4 rows above (and the remaining 3 at the top) are moved 1 pixel more to the right than the set directly below them.
- `Italic:` The character's resolution is quadrupled (e.g. a character that is normally `9x12` becomes `36x48`). The bottom 2 rows of pixels stay fixed, while every set of 4 rows above (and the remaining 2 at the top) are moved 1 pixel more to the right than the set directly below them.

> [!NOTE]
> Sometimes Minecraft, at least on version 1.16.5 renders italic text inconsistently. Given all other versions of the game render text at [triple the resolution](/scripts/font/images/correct-italic.png), the [quadruple resolution version](/scripts/font/images/incorrect-italic.png) was deemed to be incorrect and wasn't included in this version of the italic font.
> Minecraft version 1.16.5 (and possibly other versions) render italic text inconsistently. The [quadruple resolution version](/scripts/images/correct-italic.png) was deemed correct and thus the [triple resolution version](/scripts/images/incorrect-italic.png) has not been included in the italic font.
>
> Further, the game seems to tuck characters into preceding ones so each vertical block is `3` pixels apart. This hasn't been included in this font either but could likely be calculated for each individual glyph by setting its width according to its height.
> Further, the game seems to [tuck characters into preceding ones](/scripts/images/italic-tucking.png). This font does not include this feature.
## Usage

Expand All @@ -23,9 +23,11 @@ Minecraft only stores the regular version of its font in its assets, utilising t
$ pnpm run create-glyphs
```

2. Replace the `directory` file path in `scripts/load-glyphs.py` with the absolute path to the `scripts/font/dist` directory. Create and open a new font in FontForge. Paste the edited script into the text area under `File > Execute Script` and click `OK`. This may take some time to execute.
2. Replace the `directory` file path in `scripts/load-glyphs.py` with the absolute path to the `scripts/font/dist` directory.

3. Generate each font using `File > Generate Fonts...`:
3. Create and open a new font in FontForge. Paste the edited script into the text area under `File > Execute Script` and click `OK`. This may take some time to execute.

4. Generate each font using `File > Generate Fonts...`:

- Format: `OpenType (CFF)`
- Uncheck `Validate Before Saving`
31 changes: 14 additions & 17 deletions scripts/create-glyphs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ const path = require('path');
const { createCanvas, Image } = require('canvas');
const charMap = require('./font/mapping/include/default.json');

// Image scaling is required for FontForge's autotrace to correctly identify edges
const IMAGE_SCALING = 8;
const ITALIC_SCALING = 3;
const ITALIC_SCALING = 4;
const sets = [
{
mapping: 0,
Expand Down Expand Up @@ -35,6 +33,8 @@ if (!fs.existsSync(regularOutDir) || !fs.existsSync(italicOutDir)) {
}

sets.forEach(({ mapping, imagePath, sideLengthX, sideLengthY }) => {
console.info(`Creating glyphs for ${imagePath}...`);

const image = new Image();
image.onload = () => {
for (let x = 0; x < image.width / sideLengthX; x++) {
Expand All @@ -55,8 +55,8 @@ sets.forEach(({ mapping, imagePath, sideLengthX, sideLengthY }) => {

// Each type has to be wrapped in a function or the output won't be saved properly
const getRegularCanvas = () => {
const IMAGE_SCALING = 8;
const canvas = createCanvas(9 * IMAGE_SCALING, 12 * IMAGE_SCALING);

const ctx = canvas.getContext('2d');

// Create the regular glyph
Expand All @@ -79,15 +79,15 @@ sets.forEach(({ mapping, imagePath, sideLengthX, sideLengthY }) => {
};

const getItalicCanvas = () => {
const IMAGE_SCALING = 6;
const canvas = createCanvas(
(9 * ITALIC_SCALING + sideLengthY) * IMAGE_SCALING,
12 * ITALIC_SCALING * IMAGE_SCALING
);

const ctx = canvas.getContext('2d');

// Create the italic glyph. To keep italics looking even across glyphs with different dimensions, we put them all on a background of the same size and apply the algorithm from there.
// BUG: At large scaling factors this creates artifacts - https://github.com/Automattic/node-canvas/issues/2397
// Create the italic glyph
ctx.imageSmoothingEnabled = false;
ctx.drawImage(
image,
Expand All @@ -101,20 +101,17 @@ sets.forEach(({ mapping, imagePath, sideLengthX, sideLengthY }) => {
sideLengthY * ITALIC_SCALING * IMAGE_SCALING
);

const blockLevels = [31, 27, 23, 19, 15, 11, 7, 3, 0];
const blockLevels = [46, 42, 38, 34, 30, 26, 22, 18, 14, 10, 6, 2, 0];
blockLevels.forEach((blockLevel, i) => {
const cursorY = blockLevel * IMAGE_SCALING;
const blockHeight =
i === blockLevels.length - 1 ? 3 * IMAGE_SCALING : 4 * IMAGE_SCALING;

const data = ctx.getImageData(
0,
blockLevel * IMAGE_SCALING,
canvas.width,
blockHeight
);
i === 0 || i === blockLevels.length - 1
? 2 * IMAGE_SCALING
: 4 * IMAGE_SCALING;

ctx.fillRect(0, blockLevel * IMAGE_SCALING, canvas.width, blockHeight);
ctx.putImageData(data, (i + 1) * IMAGE_SCALING, blockLevel * IMAGE_SCALING);
const data = ctx.getImageData(0, cursorY, canvas.width, blockHeight);
ctx.fillRect(0, cursorY, canvas.width, blockHeight);
ctx.putImageData(data, (i + 1) * IMAGE_SCALING, cursorY);
});

invertColors(ctx, canvas.width, canvas.height);
Expand Down
Loading

0 comments on commit 996da9e

Please sign in to comment.