<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="content-type">
    <title>Cairo OCaml Tutorial</title>
    <link rel="stylesheet" href="tutorial.css" type="text/css" />
  </head>
  <body>
<h1>Cairo API</h1>

<ul>
  <li><a href="html/Cairo/">Cairo</a> — The main cairo functions</li>
  <li><a href="doc/cairo2-gtk/Cairo_gtk/">Cairo_gtk</a> — Integration of Cairo
    with labgtk2 (if the later is available).</li>
  <li><a href="doc/cairo2-pango/Cairo_pango/">Cairo_pango</a>
    — Integration of Cairo
    with pango (if the later is available).</li>
</ul>


<h1>Cairo OCaml Tutorial</h1>

<div id="content">

<p>
This tutorial is derived from Michael
Urman's <a href="http://www.tortall.net/mu/wiki/CairoTutorial">cairo
tutorial for python programmers</a> and
the <a href="http://cairographics.org/tutorial/">Cairo
Tutorial</a>. The original code snippets have been translated to
OCaml, the text has only been changed as much as necessary.
This version is released with the permission of Michael Urman
and is licensed under the GLP v3.
</p>
<p>
In order to follow along on your computer, you need the following
things:</p>

<ol>
<li><a href="http://cairographics.org/">Cairo</a> itself. You will
need both the library and the development files. See Download if you
don't have it
already.</li><li><a href="https://ocaml.org/">OCaml</a> to run the
code snippets,
and</li><li>The <a href="https://github.com/Chris00/ocaml-cairo">OCaml
Cairo bindings</a> to join the previous two.</li>
</ol>

<p>If you want to see the code snippets included in this tutorial in
action, you can try to click on some of the images. You will get a
small OCaml program which includes the described drawing code.</p>


<h2>Table of contents</h2>

<ol>
  <li><a href="#drawing_model">Cairo's Drawing Model</a>
    <ul><li>
	<a href="#nouns">Nouns</a>
      (<a href="#Destination">Destination</a>,
      <a href="#Source">Source</a>,  <a href="#Mask">Mask</a>,
      <a href="#Path">Path</a>, <a href="#Context">Context</a>) </li>
      <li><a href="#Verbs">Verbs</a>
	(<a href="#Stroke">Stroke</a>,  <a href="#Fill">Fill</a>,
	<a href="#Showtext">Show Text / Glyphs</a>,
	<a href="#Paint">Paint</a>,
	<a href="#Mask">Mask</a>)
      </li>
    </ul>
</li><li><a href="#drawing_with_cairo">Drawing with Cairo</a>
    <ul>
      <li><a href="#preparesource">Preparing and Selecting a Source</a></li>
      <li><a href="#createpath">Creating a Path</a>
	(<a href="#Moving">Moving</a>,
	<a href="#Lines">Straight Lines</a>,
	<a href="#Arcs">Arcs</a>,
	<a href="#Curves">Curves</a>,
	<a href="#Closepath">Close the path</a>,
	<a href="#Text">Text</a>)
      </li>
    </ul>
</li>
<li><a href="#Understandingtext">Understanding Text</a></li>
<li><a href="#Transforms">Working with Transforms</a></li>
<li><a href="#Gonext">Where to Go Next</a></li>
<li><a href="#Tips">Tips and Tricks</a>
    <ul>
      <li><a href="#linewidth">Line Width</a></li>
      <li><a href="#textalign">Text Alignment</a></li>
    </ul>
</li>
<li><a href="html/Cairo/">OCaml Cairo API</a>
</li>
</ol>

<h2><a id="drawing_model"></a>Cairo's Drawing Model</h2>

<p>In order to explain the operations used by cairo, we first delve into a
model of how cairo models drawing. There are only a few concepts
involved, which are then applied over and over by the different
methods. First I'll describe the <a href="#Nouns">nouns</a>: <a href="#Destination">destination</a>, <a href="#Source">source</a>, <a href="#Mask">mask</a>,
<a href="#Path">path</a>, and <a href="#Context">context</a>. After that I'll describe the verbs which offer ways
to manipulate the nouns and draw the graphics you wish to create.<br>

<h3 id="Nouns">Nouns</h3>

<p>Cairo's nouns are somewhat abstract. To make them concrete I'm
including diagrams that depict how they interact. The first three nouns
are the three layers in the diagrams you see in this section. The
fourth noun, the path, is drawn on the middle layer when it is
relevant. The final noun, the context, isn't shown.</p>

<h3 id="Destination">Destination</h3>
<div class="tutright"><img src="destination.png" alt=""></div>

<p>The destination is the
<a href="html/Cairo/">surface</a> on which
you're drawing. It may be tied to an array of pixels like in this
tutorial, or it might be tied to a SVG or PDF file, or something else.
This surface collects the elements of your graphic as you apply them,
allowing you to build up a complex work as though painting on a canvas.</p>

<h3 id="Source">Source</h3>

<div class="tutright"><img src="source.png" alt=""></div>

<p>The source
is the "paint" you're about to work with. I show this as it
is&#8212;plain black for several examples&#8212;but translucent to
show lower layers.  Unlike real paint, it doesn't have to be a single
color; it can be a <a href="html/Cairo/Pattern/">pattern</a>
or even a previously created
destination <a href="html/Cairo/">surface</a>. Also unlike
real paint it can contain transparency information&#8212;the Alpha
channel.</p>

<h3 id="Mask">Mask</h3>

<div class="tutright"><img src="the-mask.png" alt=""></div>
<p>The mask is the most important piece: it controls where you apply
the source to the destination. I will show it as a yellow layer with holes
where it lets the source through. When you apply a drawing verb, it's like you
stamp the source to the destination. Anywhere the mask allows, the source is
copied. Anywhere the mask disallows, nothing happens.</p>

<h3 id="Path">Path</h3>

<p>The path is somewhere between part of the mask and part of the
context. I will show it as thin green lines on the mask layer. It is
manipulated by path verbs, then used by drawing verbs.</p>

<h3><a id="Context"></a>Context</h3>

<p>The context keeps track of everything that verbs affect.  It tracks
one source, one destination, and one mask.  It also tracks several
helper variables like your line width and style, your font face and
size, and more. Most importantly it tracks the path, which is turned
into a mask by drawing verbs.</p>

<p>Before you can start to draw something with cairo, you need to create
the context. The context is stored in cairo's central data type, called
<code><a href="html/Cairo/#TYPEcontext">Cairo.context</a></code>. When
you create a cairo context, it must be tied to a specific surface-for
example, an image surface if you want to create a PNG file.  There is
also a data type for the surface, called
<code><a href="html/Cairo/Surface/#TYPEt">Cairo.Surface.t</a></code>.
You can initialize your cairo context like this:</p>

<pre><code>let surface = <a href="html/Cairo/Image/#VALcreate">Cairo.Image.create</a> Cairo.Image.ARGB32 ~w:120 ~h:120
let cr = <a href="html/Cairo/#VALcreate">Cairo.create</a> surface
</code></pre>

<p>The cairo context in this example is tied to an image surface of
dimension 120&nbsp;x&nbsp;120 and 32 bits per pixel to store RGB and
Alpha information. Surfaces can be created specific to most cairo
backends, see the <a href="html/Cairo/">manual</a> for details.</p>

<h3 id="Verbs">Verbs</h3>

<p>The reason you are using cairo in a program is to draw. Cairo
internally draws with one fundamental drawing operation: the source
and mask are freely placed somewhere over the destination. Then the
layers are all pressed together and the paint from the source is
transferred to the destination wherever the mask allows it. To that
extent the following five drawing verbs, or operations, are all
similar. They differ by how they construct the mask.</p>

<h3 id="Stroke">Stroke</h3>

<div class="tutright">
  <a href="../examples/stroke.ml"><img src="stroke.png" alt=""></a></div>

<p>The
<a href="html/Cairo/#VALstroke"><code>Cairo.stroke</code></a>
operation takes a virtual pen along the path. It allows the source to
transfer through the mask in a thin (or thick) line around the path,
according to the pen's
<a href="html/Cairo/#VALset_line_width">line width</a>,
<a href="html/Cairo/#VALset_dash">dash style</a>,
and <a href="html/Cairo/#VALset_line_cap">line caps</a>.</p>

<pre><code>Cairo.set_line_width cr 0.1;
Cairo.set_source_rgb cr 0. 0. 0.;
Cairo.rectangle cr 0.25 0.25 ~w:0.5 ~h:0.5;
Cairo.stroke cr;
</code></pre>


<h3 id="Fill">Fill</h3>

<div class="tutright"><a href="../examples/fill.ml"><img src="fill.png"
alt=""></a></div>

<p>The
<a href="html/Cairo/#VALfill"><code>Cairo.fill</code></a> operation
instead uses the path like the lines of a coloring book, and allows
the source through the mask within the hole whose boundaries are the
path. For complex paths (paths with multiple closed sub-paths-like a
donut-or paths that self-intersect) this is influenced by the
<a href="html/Cairo/#VALset_fill_rule">fill rule</a>.  Note that while
stroking the path transfers the source for half of the line width on
each side of the path, filling a path fills directly up to the edge of
the path and no further.</p>

<pre><code>Cairo.set_source_rgb cr 0. 0. 0.;
Cairo.rectangle cr 0.25 0.25 ~w:0.5 ~h:0.5;
Cairo.fill cr;
</code></pre>


<h3 id="Showtext">Show Text / Glyphs</h3>

<div class="tutright"><a href="../examples/showtext.ml"><img src="showtext.png"
alt=""></a></div>

<p>The
<a href="html/Cairo/#VALshow_text"><code>Cairo.show_text</code></a>
operation forms the mask from text. It may be easier to think of
<code>Cairo.show_text</code> as a shortcut for creating a path with
<a href="html/Cairo/Path/#VALtext"><code>Cairo.Path.text</code></a>
and then using
<a href="html/Cairo/#VALfill"><code>Cairo.fill</code></a> to transfer
it.  Be aware <code>Cairo.show_text</code> caches glyphs so is much
more efficient if you work with a lot of text.</p>

<pre><code>Cairo.set_source_rgb cr 0.0 0.0 0.0;
<a href="html/Cairo/#VALselect_font_face">Cairo.select_font_face</a> cr "Georgia" ~weight:Cairo.Bold;
Cairo.set_font_size cr 1.2;
let te = <a href="html/Cairo/#VALtext_extents">Cairo.text_extents</a> cr "a" in
Cairo.move_to cr (0.5 -. te.width /. 2. -. te.x_bearing)
    (0.5 -. te.height /. 2. -. te.y_bearing);
Cairo.show_text cr "a";
</code></pre>

<h3 id="Paint">Paint</h3>

<div class="tutright"><a href="../examples/paint.ml"><img src="paint.png"
alt=""></a></div>

<p>The
<a href="html/Cairo/#VALpaint"><code>Cairo.paint</code></a>
operation uses a mask that transfers the entire source to the
destination. Some people consider this an infinitely large mask, and
others consider it no mask; the result is the same. The related
operation
<a href="html/Cairo/#VALpaint"><code>Cairo.paint ~alpha:true</code></a>
similarly allows transfer of the full source to destination, but it
transfers only the provided percentage of the color.</p>

<pre><code>Cairo.set_source_rgb cr 0.0 0.0 0.0;
Cairo.paint cr ~alpha:0.5;
</code></pre>

<h3 id="Mask">Mask</h3>

<div class="tutright"><a href="../examples/mask.ml"><img src="mask.png"
alt=""></a></div>

<p>The
<a href="html/Cairo/#VALmask"><code>Cairo.mask</code></a>
and
<a href="html/Cairo/#VALmask_surface"><code>Cairo.mask_surface</code></a>
operations allow transfer according to the transparency/opacity of a
second source pattern or surface. Where the pattern or surface is
opaque, the current source is transferred to the destination.  Where
the pattern or surface is transparent, nothing is transferred.</p>

<pre><code>let linpat = Cairo.Pattern.create_linear ~x0:0. ~y0:0. ~x1:1. ~y1:1. in
Cairo.Pattern.add_color_stop_rgb linpat 0. 0.3 0.8;
Cairo.Pattern.add_color_stop_rgb linpat ~ofs:1. 0. 0.8 0.3;

let radpat = Cairo.Pattern.create_radial ~x0:0.5 ~y0:0.5 ~r0:0.25
                                         ~x1:0.5 ~y1:0.5 ~r1:0.75 in
Cairo.Pattern.add_color_stop_rgba radpat 0. 0. 0. 1.;
Cairo.Pattern.add_color_stop_rgba radpat ~ofs:0.5 0. 0. 0. 0.;

Cairo.set_source cr linpat;
Cairo.mask cr radpat;
</code></pre>



<h1 id="drawing_with_cairo">Drawing with Cairo</h1>

<p>In order to create an image you desire, you have to prepare the
<a href="html/Cairo/#TYPEcontext">context</a> for each of the drawing
verbs.  To use
<a href="html/Cairo/#VALstroke"><code>Cairo.stroke</code></a> or
<a href="html/Cairo/#VALfill"><code>Cairo.fill</code></a>
you first need a path.  To use
<a href="html/Cairo/#VALshow_text"><code>Cairo.show_text</code></a>
you must position your text by its insertion point. To use
<a href="html/Cairo/#VALmask"><code>Cairo.mask</code></a>
you need a second source
<a href="html/Cairo/Pattern/">pattern</a> or
<a href="html/Cairo/Surface/">surface</a>.
And to use any of the operations, including
<a href="html/Cairo/#VALpaint"><code>Cairo.paint</code></a>,
you need a primary source.</p>

<h2 id="preparesource">Preparing and Selecting a Source</h2>

<p>There are three main kinds of sources in cairo: colors, gradients,
and images. Colors are the simplest; they use a uniform hue and
opacity for the entire source. You can select these without any
preparation with
<a href="html/Cairo/#VALset_source_rgb"><code>Cairo.set_source_rgb</code></a>
and
<a href="html/Cairo/#VALset_source_rgba"><code>Cairo.set_source_rgba</code></a>.
Using <code>Cairo.set_source_rgb cr r g b</code> is equivalent to
using
<code>Cairo.set_source_rgba cr r g b 1.0</code>, and it sets your source
color to use full opacity.</p>

<div class="tutright"><a href="../examples/setsourcergba.ml"
><img src="setsourcergba.png" alt=""></a></div>

<pre><code>Cairo.set_source_rgb cr 0. 0. 0.;
Cairo.move_to cr 0. 0.;
Cairo.line_to cr 1. 1.;
Cairo.move_to cr 1. 0.;
Cairo.line_to cr 0. 1.;
Cairo.set_line_width cr 0.2;
Cairo.stroke cr;

Cairo.rectangle cr 0. 0. ~w:0.5 ~h:0.5;
Cairo.set_source_rgba cr 1. 0. 0. 0.80;
Cairo.fill cr;

Cairo.rectangle cr 0. 0.5 ~w:0.5 ~h:0.5;
Cairo.set_source_rgba cr 0. 1. 0. 0.60;
Cairo.fill cr;

Cairo.rectangle cr 0.5 0. ~w:0.5 ~h:0.5;
Cairo.set_source_rgba cr 0. 0. 1. 0.40;
Cairo.fill cr;
</code></pre>

<p>Gradients describe a progression of colors by setting a start and
stop reference location and a series of "stops" along the
way. <a href="html/Cairo/Pattern/#VALcreate_linear">Linear
gradients</a> are built from two points which pass through parallel
lines to define the start and stop
locations. <a href="html/Cairo/Pattern/#VALcreate_radial">Radial
gradients</a> are also built from two points, but each has an
associated radius of the circle on which to define the start and stop
locations. Stops are added to the gradient with
<a href="html/Cairo/Pattern/#VALadd_color_stop_rgb"
><code>Cairo.Pattern.add_color_stop_rgb</code></a> and
<a href="html/Cairo/Pattern/#VALadd_color_stop_rgba"
><code>Cairo.Pattern.add_color_stop_rgba</code></a> which take a
color like <code>Cairo.set_source_rgb*</code>, as well as an offset
to indicate where it lies between the reference locations. The colors
between adjacent stops are averaged over space to form a smooth blend.
Finally, the behavior beyond the reference locations can be controlled
with
<a href="html/Cairo/Pattern/#VALset_extend"
><code>Cairo.Pattern.set_extend</code></a>.</p>

<div class="tutright"><a href="../examples/setsourcegradient.ml"
><img src="setsourcegradient.png" alt=""></a></div>

<pre><code>let radpat = Cairo.Pattern.create_radial ~x0:0.25 ~y0:0.25 ~r0:0.1
                                         ~x1:0.5  ~y1:0.5  ~r1:0.5 in
Cairo.Pattern.add_color_stop_rgb radpat  1.0 0.8 0.8;
Cairo.Pattern.add_color_stop_rgb radpat ~ofs:1.  0.9 0.0 0.0;

for i=1 to 9 do
  for j=1 to 9 do
    Cairo.rectangle cr (float i /. 10. -. 0.04)
                       (float j /. 10. -. 0.04) ~w:0.08 ~h:0.08;
  done
done;
Cairo.set_source cr radpat;
Cairo.fill cr;

let linpat = Cairo.Pattern.create_linear ~x0:0.25 ~y0:0.35
                                         ~x1:0.75 ~y1:0.65 in
Cairo.Pattern.add_color_stop_rgba linpat ~ofs:0.00  1. 1. 1. 0.0;
Cairo.Pattern.add_color_stop_rgba linpat ~ofs:0.25  0. 1. 0. 0.5;
Cairo.Pattern.add_color_stop_rgba linpat ~ofs:0.50  1. 1. 1. 0.0;
Cairo.Pattern.add_color_stop_rgba linpat ~ofs:0.75  0. 0. 1. 0.5;
Cairo.Pattern.add_color_stop_rgba linpat ~ofs:1.00  1. 1. 1. 0.0;

Cairo.rectangle cr 0.0 0.0 ~w:1. ~h:1.;
Cairo.set_source cr linpat;
Cairo.fill cr;
</code></pre>

<p>Images include both surfaces loaded from existing files with
<a href="html/Cairo/PNG/#VALcreate"
><code>Cairo.PNG.create</code></a> and surfaces created
from within cairo as an earlier destination. As of cairo 1.2, the
easiest way to make and use an earlier destination as a source is with
<a href="html/Cairo/Group/#VALpush"><code>Cairo.Group.push</code></a>
and either
<a href="html/Cairo/Group/#VALpop"><code>Cairo.Group.pop</code></a>
or
<a href="html/Cairo/Group/#VALpop_to_source"
><code>Cairo.Group.pop_to_source</code></a>.
Use <code>Cairo.Group.pop_to_source</code> to use it just until you
select a new source, and <code>Cairo.Group.pop</code> when you want
to save it so you can select it over and over again with
<a href="html/Cairo/#VALset_source"
><code>Cairo.set_source</code></a>.</p>


<h2 id="createpath">Creating a Path</h2>

<p>Cairo always has an active path. If you
call <a href="#Stroke"><code>Cairo.stroke</code></a> it will draw
the path with your line settings.  If you
call <a href="#Fill"><code>Cairo.fill</code></a> it will fill the
inside of the path.  But as often as not, the path is empty, and both
calls will result in no change to your destination. Why is it empty so
often? For one, it starts that way; but more importantly after each
<a href="#Stroke"><code>Cairo.stroke</code></a>
or <a href="#Fill"><code>Cairo.fill</code></a> it is emptied again to
let you start building your next path.</p>

<p>What if you want to do multiple things with the same path? For
instance to draw a red rectangle with a black border, you would want
to fill the rectangle path with a red source, then stroke the same
path with a black source. A rectangle path is easy to create multiple
times, but a lot of paths are more complex.</p>

<p>Cairo supports easily reusing paths by having alternate versions of
its operations. Both draw the same thing, but the alternate doesn't
reset the path.  For stroking, alongside
<a href="html/Cairo/#VALstroke"><code>Cairo.stroke()</code></a>
there is
<a href="html/Cairo/#VALstroke"><code>Cairo.stroke
~preserve:true</code></a>; for filling,
<a href="html/Cairo/#VALfill"><code>Cairo.fill
~preserve:true</code></a> joins
<a href="html/Cairo/#VALfill"><code>Cairo.fill</code></a>.
Even setting the clip has a preserve option.  Apart from choosing when
to preserve your path, there are only a couple common operations.</p>

<h3 id="Moving">Moving</h3>

<div class="tutright"><img src="path-moveto.png" alt=""></div>

<p>Cairo uses a connect-the-dots style system when creating paths.  Start
at 1, draw a line to 2, then 3, and so forth. When you start a path, or
when you need to start a new sub-path, you want it to be like point 1:
it has nothing connecting to it. For this, use
<a href="html/Cairo/#VALmove_to"><code>Cairo.move_to</code></a>.
This sets the current reference point without making the path connect
the previous point to it. There is also a relative coordinate variant,
<a href="html/Cairo/#VALrel_move_to"><code>Cairo.rel_move_to</code></a>,
which sets the new reference a specified distance away from the
current reference instead. After setting your first reference point,
use the other path operations which both update the reference point
and connect to it in some way.</p>

<pre><code>Cairo.move_to cr 0.25 0.25;
</code></pre>

<h3 id="Lines">Straight Lines</h3>

<div class="tutright"><img src="path-lineto.png" alt=""></div>

<p>Whether with absolute coordinates
<a href="html/Cairo/#VALline_to"><code>Cairo.line_to</code></a>
(extend the path from the reference to this point), or relative
coordinates
<a href="html/Cairo/#VALrel_line_to"
><code>Cairo.rel_line_to</code></a> (extend the path from the
reference this far in this direction), the path connection will be a
straight line. The new reference point will be at the other end of the
line.</p>

<pre><code>Cairo.line_to cr 0.5 0.375;
Cairo.rel_line_to cr 0.25 (-0.125);
</code></pre>

<h3 id="Arcs">Arcs</h3>

<div class="tutright"><img src="path-arcto.png" alt=""></div>

<p>Arcs are parts of the outside of a circle. Unlike straight lines,
the point you directly specify is not on the path. Instead it is the
center of the circle that makes up the addition to the path. Both a
starting and ending point on the circle must be specified, and these
points are connected either clockwise by
<a href="html/Cairo/#VALarc"><code>Cairo.arc</code></a>
or counter-clockwise by
<a href="html/Cairo/#VALarc_negative"><code>Cairo.arc_negative</code></a>.
If the previous reference point is not on this new curve, a straight
line is added from it to where the arc begins. The reference point is
then updated to where the arc ends. There are only absolute
versions.</p>

<pre><code>let pi_4 = atan 1. in
Cairo.arc cr 0.5 0.5 ~r:(0.25 *. sqrt 2) ~a1:(-. pi_4) ~a2:pi_4;
</code></pre>

<h3 id="Curves">Curves</h3>

<div class="tutright"><img src="path-curveto.png" alt=""></div>

<p>Curves in cairo are cubic B&eacute;zier splines. They start at the current
reference point and smoothly follow the direction of two other points
(without going through them) to get to a third specified point. Like
lines, there are both absolute
(<a href="html/Cairo/#VALcurve_to"><code>Cairo.curve_to</code></a>)
and relative (<a href="html/Cairo/#VALrel_curve_to"
><code>Cairo.rel_curve_to</code></a>) versions.  Note that the
relative variant specifies all points relative to the previous
reference point, rather than each relative to the preceding control
point of the curve.</p>

<pre><code>Cairo.rel_curve_to cr (-0.25) (-0.125) (-0.25) 0.125 (-0.5) 0.;
</code></pre>

<h3 id="Closepath">Close the path</h3>

<div class="tutright"><a href="../examples/path_close.ml"
><img src="path-close.png" alt=""></a></div>

<p>Cairo can also close the path by drawing a straight line to the
beginning of the current sub-path. This straight line can be useful
for the last edge of a polygon, but is not directly useful for
curve-based shapes. A closed path is fundamentally different from an
open path: it's one continuous path and has no start or end. A closed
path has no line caps for there is no place to put them.</p>

<pre><code>Cairo.Path.close cr;
</code></pre>

<h3 id="Text">Text</h3>

<p>Finally text can be turned into a path with
<a href="html/Cairo/Path/#VALtext"><code>Cairo.Path.text</code></a>.
Paths created from text are like any other path, supporting stroke or
fill operations. This path is placed anchored to the current reference
point, so <a href="#Moving"><code>Cairo.move_to</code></a> your
desired location before turning text into a path.  However there are
performance concerns to doing this if you are working with a lot of
text; when possible you should prefer using the
verb <a href="#Showtext"><code>Cairo.show_text</code></a>
over <code>Cairo.Path.text</code>
and <a href="#Fill"><code>Cairo.fill</code></a>.</p>


<h1 id="Understandingtext">Understanding Text</h1>

<div class="tutright"><a href="../examples/textextents.ml"
><img src="textextents.png" alt=""></a></div>

<p>To use text effectively you need to know where it will go. The methods
<a href="html/Cairo/#VALfont_extents"><code>Cairo.font_extents</code></a>
and
<a href="html/Cairo/#VALtext_extents"><code>Cairo.text_extents</code></a>
get you this information. Since this diagram is hard to see so small,
I suggest running the <a href="../examples/textextents.ml">source</a>
and looking at its output.  It shows the relation between the
reference point (red dot); suggested next reference point (blue dot);
bounding box (dashed blue lines); bearing displacement (solid blue
line); and height, ascent, baseline, and descent lines (dashed
green).</p>

<p>The reference point is always on the baseline.  The descent line is
below that, and reflects a rough bounding box for all characters in
the font. However it is an artistic choice intended to indicate
alignment rather than a true bounding box. The same is true for the
ascent line above. Next above that is the height line, the
artist-recommended spacing between subsequent baselines. All three of
these are reported as distances from the baseline, and expected to be
positive despite their differing directions.</p>

<p>The bearing is the displacement from the reference point to the
upper-left corner of the bounding box. It is often zero or a small
positive value for x displacement, but can be negative x for
characters like j as shown; it's almost always a negative value for y
displacement. The width and height then describe the size of the
bounding box. The advance takes you to the suggested reference point
for the next letter. Note that bounding boxes for subsequent blocks of
text can overlap if the bearing is negative, or the advance is smaller
than the width would suggest.</p>

<p>In addition to placement, you also need to specify a face, style,
and size.  Set the face and style together with
<a href="html/Cairo/#VALselect_font_face"
><code>Cairo.select_font_face</code></a>, and the size with
<a href="html/Cairo/#VALset_font_size"
><code>Cairo.set_font_size</code></a>.  If you need even finer
control, try getting a
<a href="html/Cairo/Font_options/#TYPEfont_options"
><code>Cairo.Font_options.t</code></a> with
<a href="html/Cairo/Font_options/#VALget"
><code>Cairo.Font_options.get</code></a>,
tweaking it, and setting it with
<a href="html/Cairo/Font_options/#VALset"
><code>Cairo.Font_options.set</code></a>.</p>


<h1 id="Transforms">Working with Transforms</h1>

<p>Transforms have three major uses. First they allow you to set up a
coordinate system that's easy to think in and work in, yet have the
output be of any size.  Second they allow you to make helper functions
that work at or around a (0, 0) but can be applied anywhere in the
output image. Thirdly they let you deform the image, turning a
circular arc into an elliptical arc, etc.  Transforms are a way of
setting up a relation between two coordinate systems. The device-space
coordinate system is tied to the surface, and cannot change. The
user-space coordinate system matches that space by default, but can be
changed for the above reasons. The helper functions
<a href="html/Cairo/#VALuser_to_device"
><code>Cairo.user_to_device</code></a>
and
<a href="html/Cairo/#VALuser_to_device_distance"
><code>Cairo.user_to_device_distance</code></a> tell you what the
device-coordinates are for a user-coordinates position or distance.
Correspondingly
<a href="html/Cairo/#VALdevice_to_user"
><code>Cairo.device_to_user</code></a>
and
<a href="html/Cairo/#VALdevice_to_user_distance"
><code>Cairo.device_to_user_distance</code></a> tell you
user-coordinates for a device-coordinates position or distance.
Remember to send positions through the non-distance variant, and
relative moves or other distances through the distance variant.</p>

<p>I leverage all of these reasons to draw the diagrams in this
document.  Whether I'm drawing 120&nbsp;&times;&nbsp;120 or
600&nbsp;&times;&nbsp;600, I use
<a href="html/Cairo/#VALscale"><code>Cairo.scale</code></a> to
give me a 1.0&nbsp;&times;&nbsp;1.0 workspace. To place the results
along the right column, such as in the discussion
of <a href="#drawing_model">cairo's drawing model</a>, I use
<a href="html/Cairo/#VALtranslate"><code>Cairo.translate</code></a>.
And to add the perspective view for the overlapping layers, I set up
an arbitrary deformation with
<a href="html/Cairo/#VALtransform"><code>Cairo.transform</code></a>
on a
<a href="html/Cairo/Matrix/#TYPEt"><code>Cairo.Matrix.t</code></a>.</p>

<p>To understand your transforms, read them bottom to top, applying
them to the point you're drawing. To figure out which transforms to
create, think through this process in reverse. For example if I want
my 1.0&nbsp;&times;&nbsp;1.0 workspace to be 100&nbsp;&times;&nbsp;100
pixels in the middle of a 120&nbsp;&times;&nbsp;120 pixel surface, I can set
it up one of three ways:</p>

<ol>
<li><code>Cairo.translate cr 10. 10.; Cairo.scale cr 100. 100.;</code></li>
<li><code>Cairo.scale cr 100. 100.; Cairo.translate cr 0.1 0.1;</code></li>
<li><code>Cairo.transform cr { Cairo.xx = 100.; yx=0.; xy=0.; yy=100.; x0=10.; y0=10. };</code></li>
</ol>

<p>Use the first when relevant because it is often the most readable; use the
third when necessary to access additional control not available with the
primary functions.</p>

<p>Be careful when trying to draw lines while under transform. Even if you

set your line width while the scale factor was 1, the line width setting
is always in user-coordinates and isn't modified by setting the scale.
While you're operating under a scale, the width of your line is
multiplied by that scale. To specify a width of a line in pixels, use
<a href="html/Cairo/#VALdevice_to_user_distance"
><code>Cairo.device_to_user_distance</code></a> to turn
a <code>(1,1)</code> device-space distance into, for example,
a <code>(0.01, 0.01)</code> user-space distance. Note that if your
transform deforms the image there isn't necessarily a way to specify a
line with a uniform width.</p>


<h1 id="Gonext">Where to Go Next</h1>

<p>This wraps up the tutorial. It doesn't cover all functions in
cairo, so for some "advanced" lesser-used features, you'll need to
look elsewhere.  The code behind the examples
(<a href="../examples/diagram.ml">layer diagrams</a>,
<a href="../examples/draw.ml">drawing illustrations</a>) uses a
handful of techniques that aren't described within, so analyzing them
may be a good first step.
Other <a href="http://cairographics.org/examples/">examples</a> on
cairographics.org
(<a href="http://forge.ocamlcore.org/plugins/scmsvn/viewcvs.php/cairo/examples/?root=archimedes">translated
to OCaml</a>) lead in different directions. As with everything,
there's a large gap between knowing the rules of the tool, and being
able to use it well. The final section of this document provides some
ideas to help you traverse parts of the gap.</p>


<h1 id="Tips">Tips and Tricks</h1>

<p>In the previous sections you should have built up a firm grasp of
the operations cairo uses to create images. In this section I've put
together a small handful of snippets I've found particularly useful or
non-obvious. I'm still new to cairo myself, so there may be other
better ways to do these things. If you find a better way, or find a
cool way to do something else, let me know and perhaps I can
incorporate it into these tips.</p>

<h2 id="linewidth">Line Width</h2>

<p>When you're working under a uniform scaling transform, you can't
just use pixels for the width of your line. However it's easy to
translate it with the help
of <code>Cairo.device_to_user_distance</code> (assuming that the pixel
width is <code>1</code>):</p>

<pre><code>let ux, uy = Cairo.device_to_user_distance cr 1. 1. in
Cairo.set_line_width cr (max ux uy);
</code></pre>

<p>When you're working under a deforming scale, you may wish to still
have line widths that are uniform in device space. For this you should
return to a uniform scale before you stroke the path. In the image,
the arc on the left is stroked under a deformation, while the arc on
the right is stroked under a uniform scale.</p>

<div class="tutright"><a href="../examples/tips_ellipse.ml"
><img src="tips_ellipse.png" alt=""></a></div>

<pre><code>Cairo.set_line_width cr 0.1;

Cairo.save cr;
Cairo.scale cr 0.5 1.;
Cairo.arc cr 0.5 0.5 ~r:0.40 ~a1:0. ~a2:two_pi;
Cairo.stroke cr;

Cairo.translate cr 1. 0.;
Cairo.arc cr 0.5 0.5 ~r:0.40 ~a1:0. ~a2:two_pi;
Cairo.restore cr;
Cairo.stroke cr;
</code></pre>


<h2 id="textalign">Text Alignment</h2>

<p>When you try to center text letter by letter at various locations,
you have to decide how you want to center it. For example the
following code will actually center letters individually, leading to
poor results when your letters are of different sizes. (Unlike most
examples, here I assume a 26&nbsp;&times;&nbsp;1 workspace.)</p>

<div class="tutright"><a href="../examples/tips_letter.ml"
><img src="tips_letter.png" alt=""></a></div>

<div class="clear"></div>

<pre><code>let alphabet = "AbCdEfGhIjKlMnOpQrStUvWxYz" in

for i = 0 to String.length alphabet - 1 do
  let letter = String.make 1 (alphabet.[i]) in
  let te = Cairo.text_extents cr letter in
  Cairo.move_to cr (float i +. 0.5 -. te.x_bearing - te.width /. 2.)
                   (0.5 -. te.y_bearing -. te.height /. 2.);
  Cairo.show_text cr letter;
done;
</code></pre>

<p>Instead the vertical centering must be based on the general size of
the font, thus keeping your baseline steady. Note that the exact
positioning now depends on the metrics provided by the font itself, so
the results are not necessarily the same from font to font.</p>

<div class="tutright"><a href="../examples/tips_font.ml"
  ><img src="tips_font.png" alt=""></a></div>

<div class="clear"></div>

<pre><code>let alphabet = "AbCdEfGhIjKlMnOpQrStUvWxYz" in

let fe = Cairo.font_extents cr in
for i = 0 to String.length alphabet - 1 do
  let letter = String.make 1 (alphabet.[i]) in
  let te = Cairo.text_extents cr letter in
  Cairo.move_to cr (float i +. 0.5 -. te.x_bearing -. te.width /. 2.)
                   (0.5 -. fe.descent +. fe.baseline /. 2.);
  Cairo.show_text cr letter;
done;
</code></pre>

<hr />

<p>Copyright &copy; 2005&ndash;2007 Michael Urman<br />
Translated to OCaml by Christophe Troestler</p>

</div> <!-- content -->




</body></html>
