Import a sequence of .svg files into FontForge as glyphs and output a font file
Asked Answered
G

1

13

I want to create a font with a large volume of glyphs. Think Japanese kanji, in the thousands. So there will definitely be some scripting / batch processing required. Luckily FontForge supports python scripting! Unluckily I haven't been able to get it working. [sadface]

Firstly, thanks to the user Hoff for posting code here that answered a big part of my question. But upon running his script I encounter problems which raise more questions:

Failed to find NameList: AGL For New Fonts
Warning: Font contained no glyphs

Updates:

  • The "font contained no glyphs" error is apparently a bug in FontForge that occurs when the font contains one or less glyph. Adding a second glyph 'B' resolved this.
  • I found the same syntax can be used whether saving .ttf .sfd .otf etc.
  • The NameList failure actually doesn't prevent the font file from being written. I was happy to discover this, but still don't understand how to provide the NameList it wants.

Here is Hoff's code:

import fontforge
font = fontforge.open('blank.sfd')
glyph = font.createMappedChar('A')
glyph.importOutlines('sourceimg.svg')
font.generate('testfont.ttf')

After five hours of struggling yesterday with building FontForge (a confusing process on a Mac). I appear to have it up and running properly. I had at first installed a pre-built version from a .dmg only to find it lacked python support. But since Hoff seemed not to encounter the same error I did, I'm not ruling out a build issue.

Either way, I don't understand the error involving AGL. What is AGL? I looked it up: "Adobe Glyph List - a standard glyph naming convention". Sounds like FontForge tried to map Unicode values to glyph names and couldn't.

So, why the AGL NameList problem? Thanks in advance for any help.

Gompers answered 2/3, 2014 at 5:11 Comment(1)
Can you post the error? Is your blank.sfd a kanji font? Maybe start with an new font: fontforge.font(). Maybe load a namelist: fontforge.loadNamelist('some_name_list.txt')Residence
R
12

Try to rebuild your Fonforge. Because the code should work. I tested it and it runs fine.

I successfully installed Fontforge with Python extension with Homebrew. This is the info:

allcaps$ brew info fontforge
fontforge: stable 20120731, HEAD
http://fontforge.org/
/usr/local/Cellar/fontforge/20120731 (377 files, 16M) *
  Built from source with: --with-x
From: https://github.com/Homebrew/homebrew/commits/master/Library/Formula/fontforge.rb
==> Dependencies
Required: gettext ✘, fontconfig ✔
Recommended: jpeg ✔, libtiff ✔
Optional: cairo ✔, pango ✘, libspiro ✘, czmq ✘
==> Options
--with-cairo
  Build with cairo support
--with-czmq
  Build with czmq support
--with-gif
  Build with GIF support
--with-libspiro
  Build with libspiro support
--with-pango
  Build with pango support
--with-x
  Build with X11 support, including FontForge.app
--without-jpeg
  Build without jpeg support
--without-libpng
  Build without libpng support
--without-libtiff
  Build without libtiff support
--without-python
  Build without python support
--HEAD
  install HEAD version
==> Caveats
Set PYTHONPATH if you need Python to find the installed site-packages:
  export PYTHONPATH=/usr/local/lib/python2.7/site-packages:$PYTHONPATH

.app bundles were installed.
Run `brew linkapps` to symlink these to /Applications.

Set PYTHONPATH
Run brew install fontforge of course with all flags you need.
Run brew linkapps

UPDATE

Start with a empty font so the font isn't the problem:

import fontforge
font = fontforge.font() # create a new font

To include a glyphlist (shouldn't be necessary) Download: http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt and then:

import fontforge
fontforge.loadNamelist('glyphlist.txt') # load a name list
...

Create the glyph by code point. createChar(uni[,name]) 'A' is 65 so

char = font.createChar(65)

Glyphs and their code points:

>>> for c in u'ABC 賢治':  print ord(c). 
>>> 65, 66, 67, 32, 36066, 27835. 

The Unicode Consortium defines the Unicode standard. The 'CJK Unified Ideographs' live in 'Basic Multilingual Plane (BMP)'.

Glyphs without a unicode point can be referenced within a font by name. And are useful for open type features or building blocks to compose new glyphs. You can create them like this:

font.createChar(-1, 'some_name')

UPDATE 2

You should name all glyphs that occur in the Adobe Glyph List by their AGL glyph name. The rest of the glyphs should be named uniXXXX where XXXX is the Unicode index. During development you can use any human readable name. So use your own naming and replace it when you generate the font for shipping. See Typophile.

Residence answered 2/3, 2014 at 23:38 Comment(12)
It's not a kanji font. The blank.sfd I made is the default encoding and I haven't yet figured out how to specify encoding via scripting. I want to try loading a namelist but don't know where to find a UTF-8 namelist file. I just learned about namelists so there's a lot I don't understand yet. I found what I thought was the full unicode set (ash.jp/code/unitbl21.htm) but then discovered it lists glyphs like ① that have no unicode number. New questions are coming up faster than answers. For a start I'll try creating a new font as you suggested instead of working from a template file. ThnxGompers
The glyphlist.txt in my update is what you are looking for. But you really shouldn't have to load it because your code runs fine on my machine. So I think there is something wrong with your build. Alternatively you could try to get or create the glyph by code point: createChar(uni[,name]) A is 65 so char = font.createChar(65).Residence
I like the idea of that approach. Where do you get the number 65 for 'A' though? Is there a standard resource like the glyphlist file but also including the code point numbers? I expect I will need to prepare a .txt file with all these values so I can keep track and also tell FontForge how to assign the glyphs properly.Gompers
My standard resource is Python for c in u'ABC 賢治': print ord(c). prints 65, 66, 67, 32, 36066, 27835. The 'CJK Unified Ideographs' live in 'Basic Multilingual Plane (BMP)'. Maybe also useful: partners.adobe.com/public/developer/en/font/…Residence
Back to your question: 'So, why the AGL NameList problem?' A: Because problems with your build. You can reinstall or use code points.Residence
I had just found the python answer a moment before you posted. Didn't see your post until after I had posted in hopes of sparing you answering, ironically. So I retract/delete that last comment. Sorry for the overlap. Yes, my build is probably the problem. I will try rebuilding. Thank you for The PDF link, it looks promising. It may solve my last question, which is: Is this a full list of all Japanese Unicode characters? ash.jp/code/unitbl21.htm Or is there a better resource I should base off of? Because as I said some characters like ① appear not to have Unicode numbers. Researching...Gompers
I don't no anything about Japanese. So I can't say it's complete or not. The Unicode Consortium defines the Unicode standard. They decide where a glyph lives. Glyphs without a unicode point can be referenced within a font by name. You can create them with createChar(-1, 'some_name') and use it as building block to compose other glyphs. Or they are referenced by some open type feature. I'll put the hints from comments into the answer. I hope it helped you. If you find this useful, upvote and if I supplied the right answer, accept.Residence
Thank you @Residence - you've answered the main question of the topic of this post. Further questions relate to Unicode character mapping and are beyond the scope of the original problem. You've been a great help. Unfortunately stackoverflow prohibited me from upvoting your answer: "Upvote requires 15 reputation". Snobbish of them, I think. I wish I could give you credit somehow for all the help you've been. Perhaps one of the holier members whose reputation is smiled upon by the stackoverflow gods can bestow an upvote blessing on my behalf. In any case thank you very much!Gompers
"Set PYTHONPATH" to what?! Installed fontforge, but got "No module found" error using it from python.Plaque
@PavelVlasov See your output of brew info fontforge. The line after: "Set PYTHONPATH if you need Python to find the installed site-packages:"Residence
@PavelVlasov you may prefer some other Python. You can always lookup the current Python with $ which python.Residence
To answer the old dangling question “Where do you get the number 65 for 'A' though?”, it's the ASCII code for A. The 0041 in the glyph list is 65 in hex, so you do already have a mapping to work from.Etoile

© 2022 - 2024 — McMap. All rights reserved.