591 lines
15 KiB
HTML
Raw Normal View History

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>
RoboThon 2006: UFO, GLIF, Robofab and NoneLab
</title>
<link href="../default.css" type="text/css" rel="stylesheet" />
<link href="../code/robothon06/py2html.css" type="text/css" rel="stylesheet" />
</head><body>
<script type="text/javascript" src="http://www.google-analytics.com/urchin.js"></script>
<script type="text/javascript">
_uacct = "UA-2044310-2";
urchinTracker();
</script>
<div id="modellogo">
<img src="../img/drawmodel_header.jpg" width="595" height="112" />
</div>
<div class="leftcontent">
<h1 class="crb-seealso">
RoboFab
</h1>
<p class="menu">
<a href="../index.html">
Home
</a>
<br />
<a href="../download/index.html">
Download v1.1.1
</a>
<br />
<a href="../intro.html">
Intro
</a>
<br />
<a href="../install.html">
Install Notes
</a>
<br />
<a href="../history.html">
History
</a>
<br />
<a href="../executive.html">
Summary
</a>
</p>
<p class="menu">
<a href="../howto/index.html">
How to's
</a>
<br />
<a href="index.html">
Step by step
</a>
<br />
<a href="../tools/dialogs.html">
Fab Dialogs
</a>
<br />
<a href="../objects/index.html">
Object reference
</a>
<br />
<a href="../objects/model.html">
Object map
</a>
<br />
<a href="../tools/index.html">
Tools
</a>
<br />
<a href="../ufo/index.html">
UFO Overview
</a>
<br />
<a href="../ufo/specification.html">
UFO Spec
</a>
<br />
<a href="../limitations.html">
Fab Limitations
</a>
<a href="../links/index.html">
Links
</a>
<br />
<a href="../credits.html">
Credits
</a>
</p>
<h1 class="crb-seealso">
Support RoboFab
</h1>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but21.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----
">
</form>
<h2 class="crb-seealso">
Up
</h2>
<p class="menu">
<p class="bonbon_uplink"><a href="index.html">Back to Step by step</a></p>
</p>
<h2 class="crb-seealso">
See also
</h2>
<p class="menu">
<a href="../howto/scripting.html">Scripting</a><br /><a href="basic.html">Basic Python</a><br /><a href="dialogkit.html">Dialog Kit</a><br /><a href="examples/index.html">RoboThon 2006</a><br /><a href="index.html">Step by step</a><br /><a href="robofab_session6.html">Production</a><br />
</p>
</div>
<div class="footer">
<a href="../feedback.html">
Feedback
</a>
<br />
<a href="../map.html">
Sitemap
</a>
<br />
Please also refer to the
<a href="../download/license.html">
Legal
</a>
<br />
Copyright 2003-2006 RoboFab
<br />
version 1.1.1
</div>
<div class="google">
<h2>RoboFab Mailinglist</h2>
<p>
Join the RoboFab users community at Google groups.
</p>
<img src="http://groups.google.com/groups/img/3nb/groups_bar.gif" alt="Google Groups" height="26" width="132" />
<p>
<form action="http://groups.google.com/group/robofab/boxsubscribe">
Email: <input type="text" name="../email" />
<input type="submit" name="../sub" value="Subscribe" />
</form>
</p>
<p>
<a href="http://groups.google.com/group/robofab">Visit this group</a>
</p>
<h2>RoboFab Sponsors</h2>
<script type="text/javascript">
google_ad_client = "pub-3703953449723704";
google_ad_width = 120;
google_ad_height = 600;
google_ad_format = "120x600_as";
google_ad_type = "text_image";
google_ad_channel ="";
google_color_border = "336699";
google_color_bg = "FFFFFF";
google_color_link = "0000FF";
google_color_url = "008000";
google_color_text = "000000";
</script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</div>
<div class="content">
<h1>
Adventures in NoneLab, scripting outside the box
</h1>
<img src="http://letterror.com/code/robofab/img/ondrawmodel_17.gif" width="140" id="smallforprint" height="96" />
<p>
Working with text sources UFO, and GLIF's. Fontlab export and import of UFO. Processing UFO's outside FontLab.
</p>
<p>Previous: <a href="robofab_session6.html">Scripting for production</a>, next: <a href="dialogkit.html">Dialog Kit</a>
</p>
<h2>UFO</h2>
<p>
Scripting a font editor without the font editor?
RoboFab can export and import to the text based <a href="http://letterror.com/code/robofab/ufo/index.html" class="reference" target="docs">UFO format</a> for font sources. You can export a FontLab font to .ufo, and you can import a .ufo to FontLab easily. Read the <a href="http://letterror.com/code/robofab/howto/makeufo.html" class="reference" target="docs">how-to</a>. UFO export and import scripts are available from the RoboFab Scripts menu. But what do you do with ufos then?
</p>
<h2>Scripting with fonts outside FontLab</h2>
<p>
The nice thing about UFO is that RoboFab can read the files even when it is not running in FontLab. The Python interpreter that you use for FontLab, can run RoboFab scripts and apply them to font and glyphs stored in a UFO rather than a .vfb. That opens possibilities for batch processing, storage in databases or version management systems, archiving or connecting your own tools to your workflow. FontLab specific functionality, such as generating font binaries, and complex path manipulations are not available in the <strong>NoneLab</strong> RoboFab, but you can make fonts, create and move glyphs, generate and manipulate kerning. We've taken great care to make sure that RoboFab based scripts work in both worlds.
</p>
<h2>NoneLab</h2>
<p>
NoneLab is a word we coined to describe Robofab/Python environments outside FontLab. Let's have a look at main the differences.
<table>
<thead>
<tr>
<td>
</td>
<td>
FontLab
</td>
<td>
NoneLab
</td>
</tr>
</thead>
<tr>
<td class="item">
Font binary generation
</td>
<td>
All formats. Import, export UFO.
</td>
<td>
Read, write UFO. Read TT, OTF, PS T1 (through fontTools). Experimental support for SVG fonts.
</td>
</tr>
<tr>
<td class="item">
CurrentFont, CurrentGlyph, AllFonts
</td>
<td>
Yes
</td>
<td>
No. Use OpenFont(aPathToUFO) instead, or open the .ufo fonts with RFont(aPathToUFO)
</td>
</tr>
<tr>
<td class="item">
Interpolation
</td>
<td>
Yes
</td>
<td>
Yes - quite a bit faster too.
</td>
</tr>
<tr>
<td class="item">
Make new fonts, move glyphs, merge, split files
</td>
<td>
Yes
</td>
<td>
Yes
</td>
</tr>
<tr>
<td class="item">
Build accented glyphs
</td>
<td>
Yes
</td>
<td>
Yes
</td>
</tr>
<tr>
<td class="item">
Manipulate kerning
</td>
<td>
Yes
</td>
<td>
Yes
</td>
</tr>
<tr>
<td class="item">
Remove overlap
</td>
<td>
Yes
</td>
<td>
No
</td>
</tr>
<tr>
<td class="item">
API
</td>
<td>
All Robofab objects. Plus the underlying FontLab objects.
</td>
<td>
All Robofab objects.
</td>
</tr>
<tr>
<td class="item">
Platform
</td>
<td>
Mac OSX, Windows, within FontLab
</td>
<td>
All platforms which support Python, Mac OSX, Windows, Linux, Unix
</td>
</tr>
<tr>
<td class="item">
Open file format
</td>
<td>
No, .vfb is a proprietary, binary file format.
</td>
<td>
Yes. UFO and GLIF formats are XML based, open and documented. You can build your own tools and use these formats.
</td>
</tr>
<tr>
<td class="item">
Widgets, UI toolkit
</td>
<td>
DialogKit, plus the set of basic windows from robofab.interface
</td>
<td>
When run as a window-less user in OSX or linux the interface things are disabled. In some Python IDE's: the set of basic windows from robofab.interface. On OSX: Vanilla.
</td>
</tr>
</table>
</p>
<h2>The UFO</h2>
<p>A UFO is not really a single file, but rather a whole folder full of stuff with a .ufo extension in the name. So you can open up a .ufo and have a look inside. Some data is stored in .plist format. This is a flavor of XML and contains kerning, lib and font info. The glyphs are stored level deeper, in the glyphs folder.
</p>
<img src="ufo.jpg" alt="UFO files and folders" width="515" id="smallforprint" height="368" />
<p>
The MyFont.ufo/glyphs/ folder contains a list of .glif files and a single contents.plist file. This is the table of contents for the folder, it contains a table of glyph name to file name mappings. So when you start working with a .ufo and you want a particular glyph, Robofab can find it faster.
</p>
<h2>The GLIF</h2>
<p>GLyph Interchange Format, a readable XML based file with all data for a single glyph: width, unicode value, all contours, points and components. The glyph.lib is also stored here.
</p>
<img src="cent.gif" alt="view of a glif" width="394" id="smallforprint" height="478" />
<p>
These screenshots are taken on an OSX machine, but the data is platform independent. Basically you can take any text editor and mess around with the points. While this is not a very efficient way to design type, it shows that the data is still there, accessible forever.
</p>
<h2>Exporting UFO</h2>
<p>
In the FontLab scripts folder that is distributed with Robofab, you will find a set of scripts for importing and exporting UFO and GLIF. Open a test font and run this script from the Macro menu. It will generate a .ufo in the same folder as the source font file.
</p>
<img src="exportmenu.gif" alt="export UFO menu" width="376" id="smallforprint" height="170" />
<p>
</p>
<h2>FontLab Remote</h2>
<p>
If you happen to be using FontLab in mac, you can use the FontLab Remote module to make FontLab receive Python instructions and data by <strong>AppleEvents.</strong> You need to start the AppleEvent handler by importing the <strong>robofab.tools.remote</strong> module. After importing it, FontLab can receive instructions by AppleEvent. You need to call remote once after starting FontLab. Now external scripts running outside FontLab can call the FontLab application, send it glyphs, get results back.
</p>
<div class="pythonsource"><pre># start the AppleEvent handler<br><span class="py_res">import</span> <span class="py_key">robofab</span>.<span class="py_key">tools</span>.<span class="py_key">remote</span></pre></div>
<div class="pythonoutput"><pre><span class="py_key">FontLabRemote</span> <span class="py_res">is</span> <span class="py_key">on</span>.</pre></div>
<p>
The following script needs to be run in a python IDE. It will ask FontLab for its current glyph, and then it will store this glyph in a new font object outside FontLab.
</p>
<div class="pythonsource"><pre># robothon06<br># demo of executing python in FontLab, MacOS only<br> <br># this script runs in the Python IDE<br># it will send some python code to FontLab<br># FontLab will execute the python code:<br># it will find the current glyph and send it to our other script.<br> <br><span class="py_res">from</span> <span class="py_key">robofab</span>.<span class="py_key">tools</span>.<span class="py_key">remote</span> <span class="py_res">import</span> <span class="py_key">runFontLabRemote</span>, <span class="py_key">receiveGlyph</span><br><span class="py_res">from</span> <span class="py_key">robofab</span>.<span class="py_key">world</span> <span class="py_res">import</span> <span class="py_key">RFont</span><br> <br># this is what we want FontLab to do:<br><span class="py_key">pythonCode</span> = <span class="py_str">"""<br>from robofab.world import CurrentGlyph<br>from robofab.tools.remote import transmitGlyph<br>g = CurrentGlyph()<br>transmitGlyph(g)<br>"""</span><br> <br># this the font where we'll store the glyph from FontLab<br><span class="py_key">destFont</span> = <span class="py_key">RFont</span>()<br> <br><span class="py_key">result</span> = <span class="py_key">runFontLabRemote</span>(<span class="py_key">pythonCode</span>)<br><span class="py_key">receiveGlyph</span>(<span class="py_key">result</span>, <span class="py_key">destFont</span>)<br><span class="py_res">print</span> <span class="py_key">destFont</span>.<span class="py_key">keys</span>()</pre></div><div class="pythonsourcetitle"><a href="examples/fontLabRemote.py" target="new">download examples/fontLabRemote.py</a></div>
<div class="pythonoutput"><pre>&lt;<span class="py_key">RGlyph</span> <span class="py_res">for</span> <span class="py_key">None</span>.<span class="py_key">parenright</span>&gt;<br>[<span class="py_str">'parenright'</span>]</pre></div>
</div>
</body></html>