larsenwork / monoid

Customisable coding font with alternates, ligatures and contextual positioning. Crazy crisp at 12px/9pt. http://larsenwork.com/monoid/
7.86k stars 170 forks source link

Font builder à la Input #2

Closed larsenwork closed 9 years ago

larsenwork commented 9 years ago

Could be cool to to let people customise without having to download first and use font squirrel - anybody with the skill to create the opentype flattening server side ?

Or any other clever idea how to do this?

chase commented 9 years ago

I can think of an approach for this that avoids dynamic generation on a server. Assuming there will only be about five or six options for customization, one could use FontForge's Python library to pop out all the possible iterations.

For example if you had two options:

  1. Slashed zero (sz)
  2. Star asterisk (sa)

Then the script could produce:

Mono16.ttf 
Mono16-Condensed.ttf 
Mono16-sz.ttf 
Mono16-Condensed-sz.ttf 
Mono16-sa.ttf 
Mono16-Condensed-sz-sa.ttf 
Mono16-sz-sa.ttf 
Mono16-Condensed-sz-sa.ttf

That may seem a little crazy, but if one were to put up a little configuration setup on the page that picks the right file name, it wouldn't be an issue. This would keep the web page static, but one would have to run the script and it would pollute the source directory.

In order to prevent polluting the source directory, one could use Travis-CI or Wercker to automatically make releases for each tagged version.

larsenwork commented 9 years ago

Good idea - I can't see there being more than 10 options at most. Haven't really played around with FontForge python library yet though.

chase commented 9 years ago

I'll hammer out an example script and put it in my fork with Wercker setup for releases. Should be done in an hour or two.

larsenwork commented 9 years ago

:+1:

larsenwork commented 9 years ago

Note that I've decided to rename them Mono16 Normal, Loose and Tight (before: Semicondensed, Normal and Condensed)

chase commented 9 years ago

Haha, well, I learned quite a few things about how FontForge handles resources... but I got my initial proof of concept knocked out: https://github.com/chase/mono16

Next steps are to make options for slashed 0 and your other alternates, remove the TTF files from the repo, and make a pull request containing instructions on how to get Wercker setup.

I'll be perfectly honest, things would be faster AND simpler if Travis CI didn't have a 3-5 day wait for adding packages to their whitelist. As soon as that happens, I'll make a branch to test how Travis CI handles things.

larsenwork commented 9 years ago

Let me know if/when you need me to do something :wink:

chase commented 9 years ago

Absolutely!

I do have one question: are you just changing the bearings to create the Loose and Tight styles from the Normal style? If that is the case, or it is something else easily automated, we could make that a build option as well.

Right now I'm refactoring how conflicting options are handled, but I should have things ready pretty soon. As always, I'm fighting with FontForge's archaic components and leftover debug messages. Currently working on a new python-fontforge Docker image that has a couple of patches to make script debugging slightly more sane.

larsenwork commented 9 years ago

Bearings: Yes, great Idea (I've modified a little bit on the Tight one but that's not critical)

Normal should be the one the two others are made from Normal -> Loose: adds 128 to RBearing Normal -> Tight: removes 128 from LBearing

I just drew Cyrillics earlier today thinking there must be some automated way to generate/update glyphs across fonts without having to copy paste ;)

I haven't really dug into the darker corners of fontforge yet but I get what you mean about archaic - but still capable as few.

larsenwork commented 9 years ago

An idea for the script

Loose: adds 128 to RBearing ½Loose: adds 64 to RBearing Normal: Unchanged ½Tight: removes 64 from LBearing Tight: removes 128 from LBearing

½Tight and ½Loose will obviously not be crisp at 16px but will for people with retina displays + at bigger font sizes

larsenwork commented 9 years ago

Would also be cool if the script could generate different vertical metrics for custom line heights :wink:

Let me know if/when you'd pursue this and I'll provide you with the values that needs to be changed

chase commented 9 years ago

Do you have a set of vertical metrics in mind or do you want it to be a dynamic option?

larsenwork commented 9 years ago

I think I'm thinking a set in order to preserve pixel accuracy.

chase commented 9 years ago

Cool! Feel free to give me the numbers for what you are thinking and I'll get around to it eventually.

larsenwork commented 9 years ago

Great! I'll need to test it with different numbers with different apps + operating systems first :)

larsenwork commented 9 years ago

I've played around with the vertical metrics and I think the default should be:

a. Win Ascent, Typo Ascent, HHead Ascent: 1792 b. Win Descent: 512 -b. Typo Descent, HHead Descent: -512

Assuming the whole process can be automated then it'd be nice to have:

Mono16-Normal-Deci: a 1664, b 512 Mono16-Normal: a 1792, b 512 Mono16-Normal-Deca: a 1792, b 640 Mono16-Normal-Hecto: a 1920, b 640 Mono16-Normal-Kilo: a 1920, b 768 Mono16-Normal-Mega: a 2048, b 768 Mono16-Normal-Giga: a 2048, b 896 Mono16-Normal-Tera: a 2176, b 896

larsenwork commented 9 years ago

Although this would probably be a better naming scheme:

Mono16-Normal-17px: a 1664, b 512 Mono16-Normal: a 1792, b 512 Mono16-Normal-19px: a 1792, b 640 Mono16-Normal-20px: a 1920, b 640 Mono16-Normal-21px: a 1920, b 768 Mono16-Normal-22px: a 2048, b 768 Mono16-Normal-23px: a 2048, b 896 Mono16-Normal-24px a 2176, b 896

chase commented 9 years ago

Awesome, I'm doing a full rewrite to make the build options more streamlined and easy to configure without an in-depth knowledge of Python. Once it is all finished, you should be able to rename it to whatever you'd like.

larsenwork commented 9 years ago

Sounds absolutely perfect! Once finished you should release the script on GitHub too

Maybe these two too since there are some crazy coders who like it tight... Mono16-Normal-15px: a 1536, b 384 Mono16-Normal-16px: a 1664, b 384

I just updated the website so you can live preview the options http://andreaslarsen.github.io/mono16/#settings

chase commented 9 years ago

I was considering making a repository for it as a separate project once finished, since it is actually quite generic as it is now.

Regarding the live preview: That's quite nifty!

larsenwork commented 9 years ago

Saw you updated the script yesterday - how far from ready is it :smile: ?

chase commented 9 years ago

I apologize it is taking me this long! It is 80% done, I just need to re-implement the conflicting and walker method to not produce and it will be done. I'm hoping I'll have some spare time tomorrow, but it may have to wait until Monday when I have the day off.

As to the reason why I am seemingly over-engineering this: I am going to be away from keyboard for about 2 months within the near future due to requirements of my real job. In my absence, I want to ensure that others will be able to easily change the configuration and not require any low-level coding for basic changes.

larsenwork commented 9 years ago

No sweat I'm just happy your doing this

chase commented 9 years ago

So here's the good news and bad news: Good news: The walker and conflicting methods are finished. Bad news: In the process of development I discovered that the build function can misbehave in some weird edge cases, so I'm going to be yet another day behind schedule.

Here's what needs to be done to make things ready for the initial pull request:

Here's what should be done later on:

larsenwork commented 9 years ago

No stress - gives me time to fine tune the website and font for "release"

I had completely forgot about this that does some of what you're doing:

https://github.com/khaledhosny/deotfy

I haven't looked at your latest code but this uses feature tags for style set (e.g. ss01) - which I guess is a plus since on style set can have many single glyph substitutions.

chase commented 9 years ago

@andreaslarsen Since you are more knowledgeable about font metrics than myself, I've got a question for you:

Is there a visual difference between these two? Original idea:

Loose: adds 128 to RBearing 
Tight: removes 128 from LBearing

Using set width (condense/extend):

Loose: adds 64 to width (RBearing and LBearing)
Tight: removes 64 from width (RBearing and LBearing)

This isn't critical, it may provide a quicker solution than what I have and also fix #6

chase commented 9 years ago

Right now the swaps are fairly slow because it does not cache a similar permutation's previous swaps and each swap preserves the original character in the alternative's original encoding slot: PyCallGraph

After I have you add the additional line-height options, this time will grow exponentially per option.

After all the options are setup, I'm guessing the whole build and deploy process will be about 4 minutes after you push changes. Is that acceptable?

larsenwork commented 9 years ago

Speed isn't an issue at all as long as it's automated then I don't care if it takes all night - it's not a script that you'd run during the design process anyway:)

About the tight loose: The difference would be loosing the pixel "perfectness" at 16px fontsize. The UPM size of the font is 2048 so at 16px every pixel is 2048/16=128 big.

This is also why ½ tight+loose will only be perfectly crisp on e.g. retina displays.

If that makes sense?

larsenwork commented 9 years ago

Would making the Tight font the "master font" speed up the script?

Tight: Master ½Tight: Tight + 64 Lbearing Normal: ½Tight + 64 Lbearing ½Loose: Normal + 64 Rbearing Loose: ½Loose + 64 Rbearing

chase commented 9 years ago

The increase turned out to be negligible for other methods of changing the bearings. The real slowdown is in glyph swapping.

chase commented 9 years ago

I improved the glyph swapping without any degradation to my knowledge. The way it swaps now assumes the two glyphs have the same slot metrics and simply swaps the foreground layer of the glyphs. I'm not sure if this would work for any characters in a swap where the metrics are not the same, but, given that Monoid is monospaced, it should not be an issue.

Now I'm just waiting on a reply from @wercker regarding whether I can skip the Docker commit step at the end of a build to make deploying a release faster.

larsenwork commented 9 years ago

:+1:

chase commented 9 years ago

Well, I got the release mechanism working after a bit of fiddling around, but the downside is that it only works once because GitHub freaks out with releases that have this many assets. I've contacted their support regarding this, but I think looking into some other kind of free storage mechanism may be better.

larsenwork commented 9 years ago

ok, maybe a stupid question but why not just make a folder named releases and put them in that?

chase commented 9 years ago

That's exactly what happens right now. When you make changes locally, you have to push and commit, right? Since this builds every time you make a new commit, this would lead to an infinite loop of builds and probably get us banned from both Github and Wercker. Technically what we could do is push to the gh-pages branch BUT that would mean that we would need to give Wercker push access, which I don't think is a good idea.

chase commented 9 years ago

Alright, so it looks like this might be a good alternative: https://www.smartfile.com/developer I'll whip up a solution to see if it can be used realistically.

EDIT: After further research it looks like deploying to the gh-pages branch will make things simpler overall and should not release the wrath of the Github overlords.

@andreaslarsen Would it be okay for the build Wercker instance to push a commit to gh-pages every time you push a commit that modifies the font source files? The only downside to this approach is that if you make any local changes to gh-pages you will have to rebase the remote branch before you push.

larsenwork commented 9 years ago

I'm not sure I understand completely but what I thought about was to simply make the script output to a local folder only when you choose to run the script.

chase commented 9 years ago

Oh, I guess I misunderstood the original issue. You want it to be a script that users run locally instead of having a configurable font ready to download like Input?

With Input, the preview page is more than a preview: what you select as options in the preview also changes what you download. I assume they are running a script on their server that does this modification prior to zipping it all up.

Unlike Input, we do not have a dynamic server to dish out customized fonts. Since Monoid's is served as static content, I assumed we could simply make a release on Github with all the available options as individual files that you would link to based on what is selected for the preview.

You, the font designer, have provided several options for your font. The font builder, as it is currently setup, has a configurable build script. It builds every single possible permutation from the options. There are currently 480 possible permutations based on that configuration. That doesn't include all the additional line heights I was going to have you add or any of the additional alternative characters you have added since I started working on it.

The original solution of putting the resulting files in a release failed. Github's Releases timeout when deleting a release with so many files. Subsequently, this means that the Wercker build process cannot replace even a single file from the release. Any updates past the initial build simply wouldn't be committed.

chase commented 9 years ago

What I am currently proposing is the following process for the Wercker bot:

  1. Ensure it has a deploy key for this repository, allowing it to act as a collaborator on this repository.
  2. Build the very large number of font permutations, put them in a temporary directory called "release".
  3. git checkout gh-pages
  4. Copy the release directory into the gh-pages branch.
  5. git add release
  6. git commit -m "Add fonts built on 19 April 2015"
  7. git push

Does this make sense to you?

larsenwork commented 9 years ago

It makes perfectly sense and you've understood the original issue - but you've just gone further.

I, font designer, run the script - but my initial thought was to just run it locally without having the script pushing the commit and/or creating releases. I would just put it in a release folder in my local clone, then maybe use some automator script to zip font files together with a readme + license txt file.

chase commented 9 years ago

I thought you agreed with my initial comment to this issue:

In order to prevent polluting the source directory, one could use Travis-CI or Wercker to automatically make releases for each tagged version.

That's why I've gone this far. What you are suggesting does not make sense to me. You want to include the hundreds of versions of the font in a zip file, then have the user wade through the filenames to pick the one that is right for them? Wouldn't it be simpler to have the website simply change the Download button's link to the proper file based on their selection using JavaScript?

I'd like to clarify: you never have to run the script. That's what Wercker does. Your only responsibility with the script is to edit build.py whenever you want to swap glyphs, add new variants, or add different line heights. Please give it a read over, it should be simple enough for anyone familiar with JavaScript to understand.

larsenwork commented 9 years ago

I do agree and sorry for not being perfectly clear but (I'm not that good at writing in english) to clarify:

Thanks for all you've done so far :+1:

chase commented 9 years ago

No need to apologize! I know that language barriers make technical projects that much more complex. If my tone came out as harsh or negative, it certainly was not intended. I look forward to closing this fairly soon!

larsenwork commented 9 years ago

Yep, especially when the technical subject is something you're not familiar with. No harshness detected.

Is it possible to swap multiple glyphs using one option, e.g.:

option('xx', 'Alternate x', Swap("x", "x.alt"), Swap("X", "X.alt")),
larsenwork commented 9 years ago

screen shot 2015-04-20 at 08 14 30

? :smile: I tried changing colman to my macbook username

chase commented 9 years ago

Regarding build options, you are very close: option('xx', 'Alternate x', [Swap("x", "x.alt"), Swap("X", "X.alt")]),

I wasn't prepared to merge the code just yet, since it still uses releases. Just a minor bump in the road, but please wait until I make a pull request before merging any of my forks in the future.

I was going to finish things up and make a pull request detailing all that was required for setting it up. Right now Wercker has two different infrastructure stacks: Andorian (1) and Ewok (5). Andorian is being phased out and they are moving toward the Docker-based infrastructure called Ewok.

Under the application settings, you can change the infrastructure stack to Ewok: Ewok

The wercker configuration is currently using this Docker image: https://registry.hub.docker.com/u/colman/py-fontforge/dockerfile

larsenwork commented 9 years ago

Sorry, should've forked it to a separate branch but was so excited to try it out. Got the script working on my machine.

I switched to ewok and promise not do do anything else (besides updating build.py) until green light is given ;)

chase commented 9 years ago

Haha, not a big problem. Would you like me to clean up the master branch to include only your font changes and then leave you a branch as it is now with your name? That way you can experiment all you want and merge/rebase/cherrypick only what should be permanent from there.

larsenwork commented 9 years ago

not quite sure what you mean - what is it you'd clean up?

chase commented 9 years ago

Basically, the cleanup process would be: Rename master to andreas: git branch -m andreas master Checkout HEAD to before the pull request merge: git checkout6898368e33a853ba77d4e341d121c770dbb673c5 Make that master: git checkout -b master Cherry-pick the font changes you made after the merge: git cherry-pick --ff9db71192b70d4d8798c05d8292bf28ea3e55c624 a320672dadcbe675fe9c2206baf44ef2ca63333f Force push the new master to Github: git push -uf origin master:master Push your experimental branch to Github: git push -u origin andreas:andreas