Closed larsenwork closed 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:
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.
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.
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.
:+1:
Note that I've decided to rename them Mono16 Normal, Loose and Tight (before: Semicondensed, Normal and Condensed)
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.
Let me know if/when you need me to do something :wink:
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.
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.
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
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
Do you have a set of vertical metrics in mind or do you want it to be a dynamic option?
I think I'm thinking a set in order to preserve pixel accuracy.
Cool! Feel free to give me the numbers for what you are thinking and I'll get around to it eventually.
Great! I'll need to test it with different numbers with different apps + operating systems first :)
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
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
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.
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
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!
Saw you updated the script yesterday - how far from ready is it :smile: ?
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.
No sweat I'm just happy your doing this
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:
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.
@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
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:
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?
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?
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
The increase turned out to be negligible for other methods of changing the bearings. The real slowdown is in glyph swapping.
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.
:+1:
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.
ok, maybe a stupid question but why not just make a folder named releases and put them in that?
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.
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.
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.
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.
What I am currently proposing is the following process for the Wercker bot:
git checkout gh-pages
git add release
git commit -m "Add fonts built on 19 April 2015"
git push
Does this make sense to you?
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.
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.
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:
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!
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")),
? :smile: I tried changing colman to my macbook username
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:
The wercker configuration is currently using this Docker image: https://registry.hub.docker.com/u/colman/py-fontforge/dockerfile
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 ;)
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.
not quite sure what you mean - what is it you'd clean up?
Basically, the cleanup process would be:
Rename master to andreas: git branch -m andreas master
Checkout HEAD to before the pull request merge: git checkout
6898368e33a853ba77d4e341d121c770dbb673c5
Make that master: git checkout -b master
Cherry-pick the font changes you made after the merge: git cherry-pick --ff
9db71192b70d4d8798c05d8292bf28ea3e55c624 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
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?