Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Ella Jameson

9
Posts
37
Followers
1
Following
A member registered Jan 04, 2018 · View creator page →

Creator of

Recent community posts

I already gave a lot of feedback in the other post which you saw, so I will only add a few extra details here. I will probably edit this later when I have more time.

  • I verified that the current “points-centric” export size does indeed allow the exported font to be used alongside other non-pixel fonts while keeping the size of both fonts the same. This is verified in Photoshop and in web browsers, so for general use, I think that the current defaults are good.
    • One persistent issue I have noticed is that the line height is too large in these situations. To get pixel-perfect spacing, I have to set the line height to 75% of the font size. So if the font is set to 16pt, the line height must be 12pt or 0.75em to get the desired line spacing. This is NOT the default behavior in Notepad and PIL for Python, where a line spacing of 0 gives the correct result.

So the issue then is that they will not display properly when used in software next to other fonts. Any font that supports specifying sizes in pts instead of px will take care of the unit conversion behind the scenes. But if the creator changed the scale, it would display too large everywhere except where the users weren’t incorrectly specifying their desired size units.

IMO the two best options (either or maybe both could be done):

  • Add the px sizes in the export dialog and make them ABOVE the pts values
  • Add a “Use pixel-centric export scaling (may display incorrectly in some places)” toggle option to the font file which will export the TTF with the scale factor my Python script converts to
(7 edits)

Just a heads up, I eventually figured out that there is no bug in Pixelforge, it actually is outputting the font at the correct scale! The issue is actually that we as users didn’t understand how fonts work! Details have been added to the main comment, but basically, points (pt) are not equal to pixels (px), and you have to do a unit converaion to find your text size in pixels or it will display 3/4 as large as you would expect.

I tracked down exactly why the line height is messed up in the export, and made a fixer script in Python: https://gist.github.com/nimaid/b255a861361e2de6e0040e6db668b38c

Then I’m not sure why it’s not working… Sorry. :/ I do know why you can’t re-import exported .ttf files and how to fix it, but IDK about .pxf files not working.

Did you save them as .pxf or .ttf?

(9 edits)

This is a bug in PixelForge that I just tracked down today. Basically, there is this value in .ttf fonts called “Units Per Em” or UPEM. This acts like a scale factor; the larger it is, the smaller the font renders.

PixelForge seems to export .ttf files with the UPEM set to 133.33% larger than it should be.

This is also the reason why the suggested font sizes do not actually render text pixel-perfectly.

Because the source code is not available, I cannot fix this issue with PixelForge directly. I can, however, fix the issue after exporting by scaling the UPEM by 75%.

The easiest way I found to do that was with Python.

Save the following script as fix_pixelforge_ttf_scaling.py:

#!/usr/bin/env python

import sys
import argparse
from pathlib import Path

from fontTools.ttLib import TTFont


# Fixes the scaling on PixelForge TTF fonts
def fix_pixelforge_ttf_scaling(font_in_path, font_out_path, scale=0.75):
    font_in_path = Path(font_in_path)
    font_out_path = Path(font_out_path)
    
    font = TTFont(font_in_path)
    
    head = font['head']
    head.unitsPerEm = round(head.unitsPerEm * scale)
    
    font.save(font_out_path)


# Parse arguments
def parse_args(args):
    parser = argparse.ArgumentParser(
        description="Fixes the Units Per Em (UPEM) value of a TTF file exported from PixelForge to make the suggested font sizes accurate.\n"
                    "Basically, there is a bug in PixelForge that makes the UPEM 133.33% larger than it should be.\n"
                    "This simply scales the UPEM down by 75%.",
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument("-i", "--input", dest="input_font", type=str, required=True,
                        help=f"the path to the TTF to convert"
                       )
    
    parser.add_argument("-o", "--output", dest="output_font", type=str, required=True,
                        help=f"the path and filename of the desired output TTF file"
                       )

    parsed_args = parser.parse_args(args)
    
    # Interpret string arguments
    input_font = Path(parsed_args.input_font)
    if not input_font.is_file():
        parser.error(f"the file \"{input_font}\" does not exist")
    parsed_args.input_font = input_font
    
    output_font = Path(parsed_args.output_font)
    if input_font.resolve(strict=False) == output_font.resolve(strict=False):
        parser.error("the output font file must be different than the input one")
    parsed_args.output_font = output_font
    
    return parsed_args


def main(args):
    print()
    parsed_args = parse_args(args)
    
    fix_pixelforge_ttf_scaling(parsed_args.input_font, parsed_args.output_font)
    print(f"Saved fixed TTF to \"{parsed_args.output_font}\"")


if __name__ == "__main__":
    main(sys.argv[1:])

You will need to install the fontTools package with pip before running this:

pip install fontTools

Run the script and fix your files as follows:

python fix_pixelforge_ttf_scaling.py -i "path/to/myfont_raw.ttf" -o "path/to/myfont_fixed.ttf"

Update!

Just a heads up, I eventually figured out that there is no bug in Pixelforge, it actually is outputting the font at the correct scale! The issue is actually that we as users didn’t understand how fonts work!

Points (pt) are NOT equal to pixels (px)!!! Points are generally in reference to a 96 DPI environment and pixels are generally in reference to a 72 DPI environment! So a pixel is equal to 96/72 points, which simplifies to px = 4/3 pt. That’s why the fonts look 3/4 as large as we expect… Because we have been taking the points size given to us via the export pop-up, and using it as the pixel size!

All my Python script is doing is converting the font to a non-standard scaling system that will render incorrectly next to other fonts of the same size. In actuality, the real fix is to use either points @ 96 DPI as your unit when setting the text size, or you convert that points value to pixels @ 72 DPI.

So for example, I made a 5 px tall font with 1 px of spacing between rows, making it 6 px tall total. The export dialog will tell me to use multiples of 6pt @ 96 DPI. If I want to figure out what pixel sizes to use instead of points, I multiply 6 by 96/72 (or 4/3), and that gives me 8px @ 72 DPI. So my font needs to be rendered at multiples of 8px @ 72 DPI.

If you still want to use the script, it is the only way to get Pixelforge to re-import a .ttf it’s exported in the past (I think the TTF import code also confuses points and pixels like we all did). But just be warned that if you try to use that modified font next to other fonts set to the same size, they will not look the same size. If you are using the pixel font as your sole font, you can probably get away with using the scaled version my script creates.

Pixelforge should really have this info included beneath the suggested points sizes, that way users won’t be confused, and they are implicitly educated that points are not equal to pixels, which it seems is not common knowledge.