fonttools/Documentation/robofabManual/site/howto/usetransformations.html
Erik van Blokland 3646055ea2 initial import
git-svn-id: http://svn.robofab.com/trunk@1 b5fa9d6c-a76f-4ffd-b3cb-f825fc41095c
2008-01-07 17:40:34 +00:00

261 lines
13 KiB
HTML

<!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>Using transformations</title>
<link href="../default.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="index.html">
How to's
</a>
<br />
<a href="../talks/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 How To</a></p>
</p>
<h2 class="crb-seealso">
See also
</h2>
<p class="menu">
<a href="../objects/anchor.html">RAnchor</a><br /><a href="../objects/bpoint.html">bPoint</a><br /><a href="../objects/component.html">RComponent</a><br /><a href="../objects/contour.html">RContour</a><br /><a href="../objects/font.html">RFont</a><br /><a href="../objects/glyph.html">RGlyph</a><br /><a href="../objects/lib.html">RLib</a><br /><a href="../objects/pen.html">Pen objects</a><br /><a href="../objects/point.html">RPoint</a><br /><a href="../objects/segment.html">RSegment</a><br /><a href="../talks/robofab_session2.html">Glyph object and Pen object</a><br /><a href="../talks/robofab_session3.html">Kerning object and glyph building</a><br /><a href="../talks/robofab_session5.html">Interpolation</a><br /><a href="glyphmath.html">Using Glyph Math</a><br /><a href="interpolate.html">How to interpolate</a><br /><a href="understandcontours.html">Understanding Contours</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>Using transformations</h1>
<p>
Matrix transformations in RoboFab are done with the help of the matrix module from fontTools. RContour, RPoint, RbPoint, RGlyph all have transform() methods which accept a matrix object.
</p>
<h2>Transform objects and the Identity transform</h2>
<p>
A Transform object from fontTools is a 2x2 transformation matrix plus offset, a.k.a. Affine transform. Transform instances are "immutable": all transforming methods, eg. rotate(), return a new Transform instance.
One way to make a new transform object is by importing the <strong>Identity</strong> transform from fontTools.misc.transform. Identity is an instance of Transform and it is initialised to transform to itself (i.e. no visible transformation). The you modify the Identity object: each method (such as rotate(), translate() etc) returns a new Transform object with the last transformation added to it.
</p>
<h3>Oh no! Math!</h3>
<p>
Transform objects are a fast and powerful way to do math with matrices. If you don't know what that means don't worry. If you follow the examples you can build Transform objects that rotate, translate and skew. Of course you can look up <strong>affine transform</strong> on google for some more in depth explanation of transformations.
</p>
<h3>Angles</h3>
<p>
Angles in all Python's math modules are measured in <strong>radians</strong> by default. A radian is a (perhaps) more scientific unit for angles than the regular "degrees", measuring the "distance travelled" over the circle rather than the angle. The length of a full circle (with radius 1) is 2 * pi. 90 degrees = 1/2 pi radians. One can easily be converted to the other using conversion methods from the math module.
</p>
<div class="pythonsource"><pre><span class="py_res">import</span> <span class="py_key">math</span><br># example of a conversion of degrees to radians<br><span class="py_res">print</span> <span class="py_key">math</span>.<span class="py_key">radians</span>(<span class="py_num">90</span>)<br> <br># example of a conversion from radians to degrees<br><span class="py_res">print</span> <span class="py_key">math</span>.<span class="py_key">degrees</span>(<span class="py_key">math</span>.<span class="py_key">pi</span>)</pre></div>
<h3>Example</h3>
<div class="pythonsource"><pre># robofab manual<br>#&nbsp; &nbsp;&nbsp; Usetransformations howto<br>#&nbsp; &nbsp; usage examples<br> <br><br><span class="py_res">from</span> <span class="py_key">fontTools</span>.<span class="py_key">misc</span>.<span class="py_key">transform</span> <span class="py_res">import</span> <span class="py_key">Identity</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">CurrentFont</span><br> <br><span class="py_key">m</span> = <span class="py_key">Identity</span><br><span class="py_res">print</span> <span class="py_key">m</span><br> <br><span class="py_key">m</span> = <span class="py_key">m</span>.<span class="py_key">rotate</span>(<span class="py_key">math</span>.<span class="py_key">radians</span>(<span class="py_num">20</span>))<br><span class="py_res">print</span> <span class="py_key">m</span><br> <br><span class="py_key">f</span> = <span class="py_key">CurrentFont</span>()<br><span class="py_res">for</span> <span class="py_key">c</span> <span class="py_res">in</span> <span class="py_key">f</span>:<br>&nbsp; &nbsp; <span class="py_key">c</span>.<span class="py_key">transform</span>(<span class="py_key">m</span>)<br>&nbsp; &nbsp; <span class="py_key">c</span>.<span class="py_key">update</span>()</pre></div><div class="pythonsourcetitle"><a href="examples/usageTransform.py" target="new">download examples/usageTransform.py</a></div>
<div class="pythonoutput"><pre>&lt; <span class="py_key">Transform</span> [<span class="py_num">1</span> <span class="py_num">0</span> <span class="py_num">0</span> <span class="py_num">1</span> <span class="py_num">0</span> <span class="py_num">0</span>] &gt;<br>&lt; <span class="py_key">Transform</span> [<span class="py_num">0.939692620786</span> <span class="py_num">0.342020143326</span><br>&nbsp; &nbsp; -<span class="py_num">0.342020143326</span> <span class="py_num">0.939692620786</span> <span class="py_num">0</span> <span class="py_num">0</span>] &gt;<br>&nbsp; &nbsp; <br># whammo</pre></div>
<h3>Methods of Transform object</h3>
<p>See the source code of fontTools.misc.transform for detailed descriptions and examples.</p>
<ul>
<li><strong>reverseTransform()</strong>: Return a new transformation, which is the other transformation transformed by self. self.reverseTransform(other) is equivalent to
other.transform(self)</li>
<li><strong>rotate(angle)</strong>: Return a new transformation, rotated by angle (in radians).</li>
<li><strong>skew(x, y)</strong>: Return a new transformation, skewed by x and y (in radians).</li>
<li><strong>scale(x=1, y=None)</strong>: Return a new transformation, scaled by x, y. The 'y' argument
may be None, which implies to use the x value for y as well.</li>
<li><strong>toPS()</strong>: returns a string with the values of the transform written out in the PostScript manner: [1 0 0 1 0 0]</li>
<li><strong>transform(other)</strong>: Return a new transformation, transformed by another transformation.</li>
<li><strong>inverse()</strong>: Return the inverse transformation.</li>
<li><strong>transformPoint((x,y))</strong>: Transform a point, i.e. apply the transformation to the point.</li>
<li><strong>transformPoints(points)</strong>: Transform a list of points.</li>
</ul>
</div>
</body></html>