Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent glyph sizes when adding glyphs from different fonts #405

Open
p3k opened this issue Sep 24, 2019 · 6 comments

Comments

@p3k
Copy link

commented Sep 24, 2019

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
@p3k

This comment has been minimized.

Copy link
Author

commented Oct 3, 2019

bump

@fizfaz

This comment has been minimized.

Copy link

commented Oct 6, 2019

The fa-solid-900.ttf font has a unitsPerEm of 512, entypo.ttf unitsPerEm of 1000. (See opentype spec for an explanation of this parameter). I guess you would have to scale the glyphs accordingly. Does this help?

@p3k

This comment has been minimized.

Copy link
Author

commented Oct 6, 2019

thanks @fizfaz for the suggestion. so how do i scale glyphs? is this a process supported by opentypejs?

@fizfaz

This comment has been minimized.

Copy link

commented 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()));
@p3k

This comment has been minimized.

Copy link
Author

commented Oct 8, 2019

thanks a lot @fizfaz the scaling works great and the glyphs look more consistent now!

i notice though that some glyphs seem to be off-centered now (e.g. a spinning loading icon made of various glyphs now wobbles unhappily instead of rotating around its circular center).

others are displayed too close to the next glyph. are there some other parameters in the glyph’s path / commands i need to scale / offset accordingly?

@p3k

This comment has been minimized.

Copy link
Author

commented 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.