Code Monkey home page Code Monkey logo

monospacifier's Introduction

monospacifier.py

A great way to increase the Unicode coverage of your favorite programming font.

monospacifier.py adjusts every character of your favorite variable-width font to match a reference monospace font. The result is a good fallback font for characters not covered by the reference: the result is a font setup with good Unicode coverage, without breaking indentation.

default vs monospacified

Pre-monospacified fonts (monospace fonts with good Unicode coverage)

Instead of running this program, you can use one of the pre-generated monospace fonts listed below (to be use as a fallback, for symbols not covered by your favorite font).

Download a fallback font

Choose from this list, based on your main programming font. Note that some fonts needed to be renamed to comply with their licenses (Asana → Asanb, STIX → STIY).

Programming font Monospacified fallback fonts
DejaVu Sans Mono Asana Math, FreeSerif, Latin Modern Math, STIX Math, Symbola, TeX Gyre Schola Math, XITS Math, XITS Math
Inconsolata LGC for Powerline Asana Math, FreeSerif, Latin Modern Math, STIX Math, Symbola, TeX Gyre Schola Math, XITS Math, XITS Math
Inconsolata Asana Math, FreeSerif, Latin Modern Math, STIX Math, Symbola, TeX Gyre Schola Math, XITS Math, XITS Math
Liberation Mono Asana Math, FreeSerif, Latin Modern Math, STIX Math, Symbola, TeX Gyre Schola Math, XITS Math, XITS Math
Source Code Pro Asana Math, FreeSerif, Latin Modern Math, STIX Math, Symbola, TeX Gyre Schola Math, XITS Math, XITS Math
Terminus (TTF) Asana Math, FreeSerif, Latin Modern Math, STIX Math, Symbola, TeX Gyre Schola Math, XITS Math, XITS Math
Ubuntu Mono Asana Math, FreeSerif, Latin Modern Math, STIX Math, Symbola, TeX Gyre Schola Math, XITS Math, XITS Math
mononoki Asana Math, FreeSerif, Latin Modern Math, STIX Math, Symbola, TeX Gyre Schola Math, XITS Math, XITS Math

If your favorite combination is not available, please let me know.

Install it

  • On Windows put the font in C:\Windows\Font.
  • On Debian-inspired systems put the font in ~/.fonts and run fc-cache.

Configure fallback

Emacs

Add the following snippet to your .emacs (replacing font names as appropriate), then restart:

(dolist (ft (fontset-list))
  (set-fontset-font ft 'unicode (font-spec :name "<monospace font>"))
  (set-fontset-font ft 'unicode (font-spec :name "<variable-width font> monospacified for <monospace font>") nil 'append))

Here are two examples:

(dolist (ft (fontset-list))
  (set-fontset-font ft 'unicode (font-spec :name "Consolas"))
  (set-fontset-font ft 'unicode (font-spec :name "Symbola monospacified for Consolas") nil 'append))
(dolist (ft (fontset-list))
  (set-fontset-font ft 'unicode (font-spec :name "DejaVu Sans Mono"))
  (set-fontset-font ft 'unicode (font-spec :name "Asanb Math monospacified for DejaVu Sans Mono") nil 'append))

urxvt

Fallback fonts can be used with urxvt using comma-separated values to the -fn switch:

urxvt -fn 'xft:Consolas,xft:Symbola monospacified for Consolas'

This can also be set in the .Xresources file:

URxvt.font: xft:Consolas,xft:Symbola monospacified for Consolas

Source it by running xrdb -merge .Xresources.

Other editors

Please submit recipes for other editors or operating systems!

Demo

inconsistent fallbacks consistent fallback monospacified fallback

Monospace font + default fallbacks — Monospace font + original Symbola — Monospace font + Monospacified Symbola

Usage

Details

  • For help, run ./monospacifier.py -h
  • For examples of use, see the Makefile (I use it to generate the files listed here)

monospacifier.py includes multiple scaling algorithms (only one is exposed on the CLI). They are all rather basic, so don't expect this program to create anything except a decent fallback font.

The most advanced algorithm (demoed) sets the bounding box of each glyph appropriately (to match the most common width in the monospace font), and slightly compresses wide characters to reduce bleeding (wide glyphs will overlap with neighboring characters), while preserving distinctions between long and short glyphs (so ↦ and ⟼ are still distinguishable). Then (conditional on the --copy-metrics flag), monospacifier.py adjusts the metrics of the newly created font to match those of the reference (this fixes a number of issues that I don't understand well, in particular with hhea_descent and os2_typodescent metrics; if you have a clue about this, please do get in touch by opening an issue).

monospacifier's People

Contributors

cpitclaudel avatar ideasman42 avatar jasongross avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

monospacifier's Issues

Feature request: scale font

Would it be possible to add the ability to scale the input fonts glyphs uniformly to fit within the width of the reference font?

Take FontAwesome as input and DejaVu Sans Mono as reference, many of the symbols from FontAwsome (the battery-icons for example) are a bit too big to fit, putting them between > and < usually makes them overlap. What I would like was for either some option to set a scale factor, or the program to calculate an optimal factor.

DBCS (particularly CJK) support

Currently all DBCS characters' widths are chopped as half after being processed by monospacifier.py.

image

image

image

(Still can be displayed in full when spaces are added between every character though)

Roboto Mono and Consolas font fallback chains

Here are best fallback chains for my liking (for Roboto Mono and Consolas).

I think that creating a single font is too restricting because of the different FOSS font licenses. Now I think it's better to write a nice UI for "Fallbacker" so end-users can create temporal fallback fonts directly on their computers - when they need a single font file. Or simply use CSS fallback chains when using Browsers and Browser-based editors.

Had to use "fontset-standard", maybe add a note

For my Emacs config on Ubuntu 15.10 I had to set the fontset in this way for some reason:
(set-fontset-font "fontset-startup" 'unicode "Symbola monospacified for Ubuntu Mono" nil 'append)

Then everything seemed to work as expected.
I'm not quite sure about the difference between "fontset-default" and "fontset-startup" and if this could be system dependent, but perhaps you could add a note about this in the readme.

Great work! I stumbled upon it setting up my mu4e config.

Dependency list

Installation on a fresh 18.04 is a drag. Even with Ubuntu I had to rerun bootstrap script a dozen of times because of missed dependencies. Please install m4, please install automake (probably irrelevant if you ever built any other package on this system), please install libtool, please install pkg-config, please use --force on each iteration because there's no skip or overwrite by default. And when you are done with it, here comes configure script with its own bunch. It didn't help either when I didn't remember how the package is called, libglib2.0-dev took me embarassing amount of time to remember when I was asked for a GLIB. And this happens on a most bloated distro you can find. I cannot speak for everybody and I understand this software is rather niche, but having a dependency list in readme.md might save someone a couple of hours, especially on a slow connection. I'll post a list of all packages I needed on 18.04 during the install in a reply below, hope it'll help.

How to Use On Windows 10?

I tried running this using Windows 10 with Linux Subsystem with Ubuntu and Python and it almost worked but got stuck on ./bootstrap and it said

please set 'build_aux' in 'bootstrap.conf'bootstrap: or add the following (or similar) to your 'configure.ac':bootstrap: AC_CONFIG_AUX_DIR([name of a directory for build scripts])

Is it possible to make a "fallbacker"?

Is it possible to make a "fallbacker" script that tunes fallback font to the main font? So that small letters would be of the same height as in main font, same for the capital letters respectively. Their weight should also be fixed independently. I know this can be done via FontForge. Is it possible to determine coefficients automatically?

And how do Monospacifier works now? Does it adjust small and capital letters independently?

Provide aggregate font zip

Would it be possible to include all fonts in one zip? It's pretty annoying to have to individually click to install them all.

Fonts licenses issues

Free fonts that you monospacify often have licenses that do not allow modified font to have any of the word from the name of the original font (OFL is the case).

So I suggest to implement another auto-naming: replace the last letter in every word to 0 or _ (and also shorten a bit):

For example Noto Sans to:

  • Not_ San_ monosp for Consolas or
  • Not0 San0 monosp for Consolas.

Feature request: Full-width characters

How difficult would it be to generate fonts with half-width characters monospacified, and full-width characters set to exactly double their width?

I am not sure how to distinguish between half- and full-width characters programmatically. Is the difference specified in Unicode, or does each font decide which characters are which width?

AttributeError, and keeping the aspect ratio?

Hi, this is an absolutely awesome tool! Thank you so much, you saved me hours of work! It still took me hours to figure out that I needed to monospace my font, and it was only luck that I stumbled across this neat little tool - it is not easy to find.

Still, I have two small issues with it. One, it sort of crashes with --copy-metrics, but it does seem to save the font anyway:

Traceback (most recent call last):
  File "./monospacifier.py", line 281, in <module>
    main()
  File "./monospacifier.py", line 267, in main
    results = list(process_fonts(args.references, args.inputs, args.save_to, args.merge, args.copy_metrics))
  File "./monospacifier.py", line 256, in process_fonts
    path = make_monospace(reference, fallback, gscaler, save_to, copy_metrics)
  File "./monospacifier.py", line 206, in make_monospace
    fscaler.copy_metrics(reference)
  File "./monospacifier.py", line 169, in copy_metrics
    setattr(self.font, metric, getattr(reference, metric))
AttributeError: 'fontforge.font' object has no attribute 'os2_capheight'

And two, the generated font's glyphs (octicons in my case) get squeezed horizontally more than vertically, so the round ones now look more like an egg rather than a circle. Would it be possible to supply a parameter that keeps the aspect ratio of the glyphs?

Or, even better in this case: keep the size of the visible "drawing" and shrink only the glyph's canvas width so that the icon might be drawn over neighbouring glyphs. I wouldn't care, I can simply add a space in front and after it, but that would look better :)

thanks!

Courier New?

If your favorite combination is not available, please let me know.

I got used to using Courier New on my Windows machine. Do you have one for that?

“TypeError: 'float' object cannot be interpreted as an integer” error on Python 3.10

Command line: ./monospacifier.py --references ./sources/references/* --inputs ./sources/inputs/* --save-to ./fonts --copy-metrics --merge

Error log:

Traceback (most recent call last):
  File "/home/lcw/fck/./monospacifier.py", line 309, in <module>
    main()
  File "/home/lcw/fck/./monospacifier.py", line 293, in main
    results = list(process_fonts(args.references, args.inputs,
  File "/home/lcw/fck/./monospacifier.py", line 284, in process_fonts
    path = make_monospace(reference, fallback, gscaler, save_to, copy_metrics, renames)
  File "/home/lcw/fck/./monospacifier.py", line 227, in make_monospace
    fscaler.scale_glyphs(gscaler)
  File "/home/lcw/fck/./monospacifier.py", line 172, in scale_glyphs
    scaler.scale(glyph)
  File "/home/lcw/fck/./monospacifier.py", line 124, in scale
    GlyphScaler.set_width(glyph, self.cell_width)
  File "/home/lcw/fck/./monospacifier.py", line 66, in set_width
    glyph.left_side_bearing += delta / 2
TypeError: 'float' object cannot be interpreted as an integer

Seems to be related with #30.

Adjustment of Nested Composite Glyphs

I'm struggling to find where nested composite glyphs are handled. (I'm reading the code, since I can't find a way to run it on my Win10x64 system).

Adjustment of simple glyphs is clearly handled with grace and consideration.

But if a simple glyph is a component in another composite glyph, the attachment points are now incorrect since the simple glyph has (or will soon be) moved. Do not the attachment points have to be adjusted to account for re-positioning of the components? Otherwise, since each glyph can be re-positioned by a different amount, attachment points for components will be incorrect.

Furthermore, composite glyphs can be arbitrarily nested, so some kind of iterative strategy seems to be needed. I'm thinking that no composite glyph can be processed until all it's components have been processed ... i.e. starting with all simple glyphs then composite glyphs that only have simple glyphs as components, then working your way up the dependency tree of composite glyphs. At each stage, a structure is needed to remember how much each component has been re-positioned.

This gets more thorny because of the scaling that is performed by monospacifier.

Finally, bounding boxes and global bounding metrics need to be re-calculated.

Am I missing something here? I am just not seeing where all this complexity is handled. Or is there some strategy going on here that handles these issues that I just don't grok.

Suggestion: Everson Mono to generate fallback fonts

I've done a lot of looking into unicode support on monospace fonts, and i haven't found anything better than Everson Mono http://www.evertype.com/emono/

Mostly I just think you should consider it as a font for merging/falling back to as it is monospace already and should scale nicely (plus it supports 11,000 unicode glyphs which is better than even most non-monospace fonts).

My everson mono + courier new merged font is working beautifully, and everson mono may be the right answer for other people as well.

Does not work in python3

At the moment monospacifier does not work with python3 and Fontforge does not appear to have bindings for python2 anymore. So even to use tauthon is not possible.

How difficult would it be to port monospacifier to python3?

Import problem

Hello :)
When I launch the python script, I have the following error: ImportError: No module named fontforge...
But fontforge is installed, and I have no errors when I try import fontforge in ptpython...
I use Manjaro.
Thanks :)

TypeError: 'NoneType' object is not iterable

$ fontforge -script monospacifier.py --input input/Raleway-* --references fonts/CourierStd.otf --copy-metrics

 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 with many parts BSD <http://fontforge.org/license.html>. Please read LICENSE.
 Based on sources from 13:38 UTC 25-Apr-2019-ML-D.
 Based on source from git with hash: f0c988e05b088411a47668c4582848165f5f0e4d
The following table(s) in the font have been ignored by FontForge
  Ignoring 'DSIG' digital signature table
Warning: Mac and Windows entries in the 'name' table differ for the
  Fullname string in the language English (US)
  Mac String: Courier Std Medium
  Windows String: CourierStd
>>> For reference font Courier Std:
The following table(s) in the font have been ignored by FontForge
  Ignoring 'DSIG' digital signature table
>>> - Monospacifying Raleway Black
Traceback (most recent call last):
  File "monospacifier.py", line 308, in <module>
    main()
  File "monospacifier.py", line 294, in main
    args.copy_metrics, args.rename))
  File "monospacifier.py", line 283, in process_fonts
    path = make_monospace(reference, fallback, gscaler, save_to, copy_metrics, renames)
  File "monospacifier.py", line 207, in make_monospace
    cleanup_font_name(fallback.fontname, renames),
  File "monospacifier.py", line 201, in cleanup_font_name
    for old, new in renames:
TypeError: 'NoneType' object is not iterable

Running Arch Linux, Compiled Fontforge from source using the following workaround: https://stackoverflow.com/questions/29441053/importerror-psmat-is-not-a-built-in-module

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.