question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Inconsistent glyph sizes when adding glyphs from different fonts

See original GitHub issue

I am trying to rewrite a Python script in Node, replacing the fontforge bindings with OpenTypeJS.

The script takes a bunch of font files and copies the desired glyphs into a subset font, creating the necessary font formats and a LESS file.

Expected Behavior

The resulting subset font should contain all glyphs in the same size.

image

Current Behavior

It works well for some fonts but as soon as a certain font file is included, those glyphs are added with smaller sizes (approx. 50%).

image

Possible Solution

I just might be missing a basic information or step to achieve the consistent glyph size. Alternatively, it might be necessary to patch the code so glyph sizes are correctly saved. (I don’t know much or enough about font tables so any assistance is appreciated.)

Steps to Reproduce (for bugs)

  1. Prepare two source fonts, entypo.ttf and fa-solid-900.ttf
  2. Create a subset font with OpenTypeJS and add two glyphs, one from each source font
  3. Compare the glyphs in the subset font with the corresponding glyphs in the source fonts

Here is a script for creating the subset font:

#!/usr/bin/env node

const fs = require('fs');
const opentype = require('opentype.js');

const glyphs = [];
const entypoFont = opentype.loadSync('entypo.ttf');
const faFont = opentype.loadSync('fa-solid-900.ttf');

const addGlyph = glyph => {
	glyph.unicode = 0xe001 + glyphs.length;
	glyph.unicodes = [glyph.unicode];
	glyph.name = 'uni' + glyph.unicode.toString(16);
	glyphs.push(glyph);
};

addGlyph(entypoFont.glyphs.get(25));
addGlyph(faFont.glyphs.get(185));

const subsetFont = new opentype.Font({
	familyName: 'Test',
	styleName: 'Regular',
	unitsPerEm: 1000,
	ascender: 800,
	descender: -200,
	glyphs: glyphs
});

fs.writeFileSync('test.ttf', Buffer.from(subsetFont.toArrayBuffer()));

And this is a visual comparison of the result (left) with the source glyphs:

image image image

Your Environment

  • Version used: OpenTypeJS 1.1.0
  • Font used: Entype and FontAweseom (see links above)
  • Browser Name and version: n.a.
  • Operating System and version (desktop or mobile): Manjaro Linux 18.1.0

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
fizfazcommented, Oct 6, 2019

Unfortunately my knowledge of opentype.js is very limited. Here I tried to just move the coordinates of the commands used in a glyph, which makes it bigger but not sure if this is enough.

image

#!/usr/bin/env node

const fs = require('fs');
const opentype = require('opentype.js');

const glyphs = [];
const entypoFont = opentype.loadSync('entypo.ttf');
const faFont = opentype.loadSync('fa-solid-900.ttf');

const addGlyph = glyph => {
 glyph.unicode = 0xe001 + glyphs.length;
 glyph.unicodes = [glyph.unicode];
 glyph.name = 'uni' + glyph.unicode.toString(16);

 // handle different unitsPerEm:
 if (glyph.path.unitsPerEm != 1000) {
    const scale = 1000/glyph.path.unitsPerEm; 
    glyph.path.commands.forEach( c => {
        c.x = Math.round(c.x * scale);
        c.y = Math.round(c.y * scale);
        if (c.x1) c.x1 = Math.round(c.x1 * scale);
        if (c.x2) c.x2 = Math.round(c.x2 * scale);
        if (c.y1) c.y1 = Math.round(c.y1 * scale);
        if (c.y2) c.y2 = Math.round(c.y2 * scale);
    });

    glyph.path.unitsPerEm = 1000;
 }

 glyphs.push(glyph);
};

addGlyph(entypoFont.glyphs.get(25));
addGlyph(faFont.glyphs.get(185));

const subsetFont = new opentype.Font({
 familyName: 'Test',
 styleName: 'Regular',
 unitsPerEm: 1000,
 ascender: 800,
 descender: -200,
 glyphs: glyphs
});

fs.writeFileSync('test.ttf', Buffer.from(subsetFont.toArrayBuffer()));
0reactions
p3kcommented, Oct 8, 2019

seems the spacing and centering issues can be ironed simply by scaling some more properties accordingly:

if (glyph.advanceWidth) glyph.advanceWidth *= scale;
if (glyph.leftSideBearing) glyph.leftSideBearing *= scale;
if (glyph.rightSideBearing) glyph.rightSideBearing *= scale;

if (glyph.xMin) glyph.xMin *= scale;
if (glyph.xMax) glyph.xMax *= scale;
if (glyph.yMin) glyph.yMin *= scale;
if (glyph.yMax) glyph.yMax *= scale;

as this solves the issue for me it could be closed. however, if someone of the opentypejs experts still would want to chime in – e.g. with a better suggestion – i leave it open for now.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why glyph set of some fonts is so incomplete or inconsistent?
Most fonts have a rather limited glyph set. Realistically making a font that is complete is a herculean feat. Supporting all possible font...
Read more >
PDF/A validation and inconsistent glyph width information
Inconsistent glyph width information is a common cause for PDF/A validation errors, but the details are not easy to understand.
Read more >
Bitmap font inconsistent pixel widths leading to incorrect ...
When I test other bitmap fonts using Raster or Hinted Raster, ... The rastered glyphs in the atlas texture seems fine but the...
Read more >
Advanced preflight inspections (Acrobat Pro) - Adobe Support
Examine the internal structure of the PDF and its fonts for ... the selected glyph and the maximum area used by all glyphs...
Read more >
Malformed “Foreign” Glyphs - Foundry Support - Monotype.
Designers who are unfamiliar with certain characters or diacritics from another language sometimes make a wild guess about their correct ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found