<!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>