Blob Blame History Raw
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<chapter id="text"
         xmlns:xi="http://www.w3.org/2003/XInclude">
  <title>Text</title>

  <epigraph>
    <attribution>Alan Perlis</attribution>
    <para>A picture is worth 10K words - but only those to describe the
    picture. Hardly any sets of 10K words can be adequately described with
    pictures.</para>
  </epigraph>

  <section id="text-introduction">
    <title>Introduction</title>

    <para>User interfaces can rely on textures to represent actions, but there
    are cases where you need to convey an idea using words.</para>

    <para>Clutter provides an actor that allows displaying and editing
    arbitrary text, called <type>ClutterText</type>. A <type>ClutterText</type>
    actor can be positioned like any other actor; its preferred size is
    determined by its contents, as well as the font family and size used to
    render those contents.</para>

  </section>

  <section id="text-shadow">
    <title>Drawing a shadow under the text</title>

    <section>
      <title>Problem</title>

      <para>You want to draw a shadow under the text displayed by a
      ClutterText actor.</para>
    </section>

    <section>
      <title>Solution</title>

      <para>Override the <function>paint</function> signal of
      <type>ClutterText</type> and use the CoglPango API to paint the
      <type>PangoLayout</type> of the actor with the color of the
      shadow at a given offset.</para>

      <screenshot>
        <mediaobject>
          <imageobject>
            <imagedata format="PNG"
                       fileref="images/text-shadow.png" />
          </imageobject>
          <alt>
            <para>A ClutterText actor painting a shadow underneath its
            contents</para>
          </alt>
        </mediaobject>
      </screenshot>
    </section>

    <section>
      <title>Discussion</title>

      <para>The <type>ClutterText</type> class provides an actor that
      transforms the <type>PangoLayout</type> object into an element of
      the Clutter scene graph. The underlying layout is painted, though,
      through a subset of the Cogl API, called
      <emphasis>CoglPango</emphasis>.</para>

      <para>It is possible to paint <type>PangoLayout</type> created by a
      <type>ClutterText</type> by invoking
      <function>cogl_pango_render_layout()</function>:</para>

      <informalexample><programlisting>
<![CDATA[
void
cogl_pango_render_layout (PangoLayout *layout,
                          int          x_offset,
                          int          y_offset,
                          CoglColor   *text_color,
                          int          flags);
]]>
      </programlisting></informalexample>

      <para>This function will paint the layout at the given offsets using the
      provided color.</para>

      <warning><para>The <function>cogl_pango_render_layout()</function>
      function will only work with <type>PangoLayout</type>s created by
      Clutter.</para></warning>

      <para>Since the shadow of the text is literally the same text but painted
      with a different color and at an offset, we can use the
      <function>paint</function> signal of <type>ClutterText</type> to paint
      the shadow, and then let <type>ClutterText</type> paint its contents on
      top:</para>

      <informalexample><programlisting>
<![CDATA[
static void
_text_paint_cb (ClutterActor *actor)
{
  ClutterText *text = CLUTTER_TEXT (actor);

  /* Get the PangoLayout that the Text actor is going to paint... */
  PangoLayout *layout;
  layout = clutter_text_get_layout (text);

  /* ... Create the color of the shadow... */

  /* ... Finally, render the Text layout at a given
   * offset using the color of the shadow
   */
  cogl_pango_render_layout (layout,
                            SHADOW_X_OFFSET, SHADOW_Y_OFFSET,
                            &color, 0);
}
]]>
      </programlisting></informalexample>

      <para>Note that we are using the <type>PangoLayout</type> of the
      <type>ClutterText</type> because the <type>ClutterText</type> actor
      always keeps an updated layout internally. It is, however, possible for
      any <type>ClutterActor</type> to create a <type>PangoLayout</type> using
      <function>clutter_actor_create_pango_layout()</function>, and then paint
      that layout using <function>cogl_pango_render_layout()</function> in
      their implementation of the <function>paint</function> virtual
      function.</para>

    </section>

    <section>
      <title>Full example</title>

      <example id="text-shadow-example">
        <title>Creating a shadow of a text</title>
        <programlisting>
          <xi:include href="examples/text-shadow.c" parse="text">
            <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
          </xi:include>
        </programlisting>
      </example>
    </section>

  </section>

</chapter>