gnome-devel-docs r633 - in trunk/gtk-drawing: . C
- From: davyd svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-devel-docs r633 - in trunk/gtk-drawing: . C
- Date: Thu, 18 Dec 2008 10:32:16 +0000 (UTC)
Author: davyd
Date: Thu Dec 18 10:32:16 2008
New Revision: 633
URL: http://svn.gnome.org/viewvc/gnome-devel-docs?rev=633&view=rev
Log:
2008-12-18 Davyd Madeley <davyd fugro-fsi com au>
* C/pango.xml:
* C/gtkdrawingarea.xml:
* C/cairo.xml:
* C/gtk-drawing.xml:
* C/cairo-pango.xml:
- add a section on painting images to Cairo surfaces
Added:
trunk/gtk-drawing/C/cairo.xml (contents, props changed)
- copied, changed from r599, /trunk/gtk-drawing/C/cairo-pango.xml
trunk/gtk-drawing/C/pango.xml
Removed:
trunk/gtk-drawing/C/cairo-pango.xml
Modified:
trunk/gtk-drawing/C/gtk-drawing.xml
trunk/gtk-drawing/C/gtkdrawingarea.xml
trunk/gtk-drawing/ChangeLog
Copied: trunk/gtk-drawing/C/cairo.xml (from r599, /trunk/gtk-drawing/C/cairo-pango.xml)
==============================================================================
--- /trunk/gtk-drawing/C/cairo-pango.xml (original)
+++ trunk/gtk-drawing/C/cairo.xml Thu Dec 18 10:32:16 2008
@@ -3,15 +3,301 @@
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
]>
-<chapter id="chapter.cairo-pango">
- <title>Cairo and Pango</title>
+<chapter id="chapter.cairo">
+ <title>Cairo</title>
- <sect1 id="sect.cairo">
- <title>Cairo</title>
- </sect1>
+ <para>
+ <ulink url="http://cairographics.org/">Cairo</ulink>
+ is a cross-platform, multi-toolkit, backend-independant vector
+ graphics library that is used extensively throughout GTK+.
+ </para>
+
+ <para>
+ This section of the manual does not aim to be a complete Cairo tutorial,
+ and instead serves to highlight how to carry out common drawing tasks
+ within GTK+ and how to optimise them. If you need a complete Cairo
+ tutorial, see <ulink url="http://cairographics.org/documentation/"/>.
+ </para>
+
+ <sect1 id="sect.cairo.masks">
+ <title>Speeding Up Drawing Using Masks</title>
+
+ <para>
+ Masks are used when drawing the same shape repeatedly. Rather than
+ recalculating a path and stroking or filling it every time, a mask can
+ be thought of like cutting one copy out of a piece of card and then
+ using it to spray paint the result onto the target surface. A Cairo mask
+ is a surface of the same type as the target surface but with only an
+ alpha channel.
+ </para>
+ <para>
+ Any sort of source may be used with a mask (e.g. a solid colour,
+ gradient or image). If you want something that uses two colours (e.g. a
+ marker with a border), you should use two marks (one for the marker and
+ one for the border).
+ </para>
+
+ <para>
+ To enable the graphics layer to accellerate the drawing of masks on your
+ target surface, the target surface should be untransformed and the mask
+ and target surface should be pixel aligned. If this isn't the case,
+ using masks may be slower than restroking the path. See <xref
+ linkend="note.cairo.masks.subpixel"/> below for more details.
+ </para>
+
+ <para>
+ Create a new mask with
+ <function>cairo_surface_create_similar</function>. Then draw your path
+ into that mask (<xref linkend="example.cairo.masks.ex1"/>). You can use
+ <function>cairo_surface_set_device_offset</function> to set the middle
+ of your mask.
+ </para>
+ <para>
+ Remember that only the alpha channel is available, so
+ use <function>cairo_set_source_rgba (cr, 0., 0., 0., a)</function>. The
+ amount of alpha in the mask is the amount of alpha that will be used
+ with the source colour when that mask is applied.
+ </para>
+ <example id="example.cairo.masks.ex1">
+ <title>Creating a Mask</title>
+ <programlisting>
+<![CDATA[#define MASK_SIZE 16
+
+cairo_surface_t *mask = cairo_surface_create_similar (
+ target_surface, CAIRO_CONTENT_ALPHA,
+ MASK_SIZE, MASK_SIZE);
+
+/* set the middle of our mask as the offset for cairo_mask_surface() */
+cairo_surface_set_device_offset (mask, MASK_SIZE / 2, MASK_SIZE / 2);
+
+cairo_t *cr = cairo_create (mask);
+/* draw into mask - remember to fill/stroke */
+cairo_destroy (cr);]]></programlisting>
+ </example>
+
+ <para>
+ To apply your mask use <function>cairo_mask_surface</function>
+ (<xref linkend="example.cairo.masks.ex2"/>). This
+ will apply the mask using your current source at the position (x, y) as
+ the top left corner of the mask (unless you offset it with
+ <function>cairo_surface_set_device_offset</function>). You do not need
+ to stroke, fill or paint the mask.
+ </para>
+
+ <example id="example.cairo.masks.ex2">
+ <title>Applying a Mask</title>
+ <programlisting>
+<![CDATA[/* cr is a cairo_t on our target surface */
+cairo_set_source_rgb (cr, 1., 0., 0.); /* mask in red */
+cairo_mask_surface (cr, mask, x, y);]]></programlisting>
+ </example>
+
+ <caution id="caution.cairo.masks.cleanup">
+ <para>
+ Remember to clean up masks you create with
+ <function>cairo_surface_destroy</function>. Otherwise they will leak.
+ </para>
+ </caution>
+
+ <note id="note.cairo.masks.subpixel">
+ <title>Sub-pixel Alignment Using Pixel Aligned Masks</title>
+
+ <para>
+ Masks must be pixel aligned with the target surface for speed, but this
+ can cause undesirable aliasing issues when drawing objects that require
+ sub-pixel alignment.
+ </para>
+ <para>
+ The trick is to create a set of masking surfaces with variously aligned
+ masking functions and then to choose the appropriate masking surface to
+ create the effect of anti-aliased drawing.
+ </para>
+ <example id="example.cairo.masks.subpixel.ex1">
+ <title>Creating and Applying Sub-pixel Aligned Masks</title>
+ <programlisting>
+<![CDATA[cairo_surface_t *mask[NSUBPX][NSUBPX];
+
+int i;
+for (i = 0; i < NSUBPX; i++)
+{
+ int j;
+ for (j = 0; j < NSUBPX; j++)
+ {
+ cairo_t *cr;
+
+ mask[i][j] = cairo_surface_create_similar (
+ target_surface,
+ CAIRO_CONTENT_ALPHA,
+ MASK_SIZE, MASK_SIZE);
+ cairo_surface_set_device_offset (mask[i][j],
+ MASK_SIZE / 2, MASK_SIZE / 2);
+
+ cr = cairo_create (mask[i][j]);
+
+ /* add a certain amount of subpixel
+ * offset for this mask */
+ cairo_translate (cr, 1. / NSUBPX * i,
+ 1. / NSUBPX * j);
+
+ draw_func (cr) /* draw onto the mask */;
+ cairo_destroy (cr);
+ }
+}
+
+double x, y;
+int xi, yi;
+
+for (...)
+{
+ x = ...; y = ...;
+
+ xi = CLAMP (((int) (x * NSUBPX + 0.5)) % NSUBPX,
+ 0, NSUBPX-1);
+ yi = CLAMP (((int) (y * NSUBPX + 0.5)) % NSUBPX,
+ 0, NSUBPX-1);
+
+ x = ((int) (x * NSUBPX + 0.5)) / NSUBPX;
+ y = ((int) (y * NSUBPX + 0.5)) / NSUBPX;
+
+ cairo_mask_surface (cr, mask[xi][yi], x, y);
+}]]></programlisting>
+ </example>
+ <para>
+ Remember to destroy the masks afterwards with
+ <function>cairo_surface_destroy</function>.
+ </para>
+ </note>
- <sect1 id="sect.pango">
- <title>Pango</title>
</sect1>
+ <sect1 id="sect.cairo.images">
+ <title>Drawing an Image to a Cairo Surface</title>
+
+ <para>
+ An almost universal requirement when doing custom drawing with GTK+ is
+ being able to add images (from a file or other buffer) onto a Cairo
+ surface.
+ </para>
+
+ <para>
+ The easiest way to do this is to load your image into a
+ <classname>GdkPixbuf</classname> (e.g. by using
+ <function>gdk_pixbuf_new_from_file</function>). This pixbuf can then be
+ converted to a Cairo source and <emphasis>painted</emphasis> onto the
+ surface using <function>gdk_cairo_set_source_pixbuf</function> and
+ <function>cairo_paint</function>
+ (<xref linkend="example.cairo.images.ex1"/>).
+ This will work with any sort of target surface.
+ </para>
+
+ <example id="example.cairo.images.ex1">
+ <title>Loading a theme icon and painting it onto a Cairo surface</title>
+ <programlisting>
+<![CDATA[GdkPixbuf *icon = gtk_icon_theme_load_icon (
+ gtk_icon_theme_get_default (),
+ GTK_STOCK_DIALOG_INFO, 48,
+ GTK_ICON_LOOKUP_USE_BUILTIN,
+ NULL);
+
+cairo_save (cr); /* save the context state before changing the source */
+
+/* position the image on the target surface */
+cairo_translate (cr, x, y);
+
+/* apply any rotation or scaling required to the image here */
+
+gdk_cairo_set_source_pixbuf (cr, icon, 0., 0.);
+cairo_paint (cr);
+
+cairo_restore (cr); /* restore the context state */
+
+g_object_unref (icon);]]></programlisting>
+ </example>
+
+ <sect2 id="sect.cairo.images.faster">
+ <title>Speeding Up Image Painting</title>
+
+ <para>
+ <classname>GdkPixbuf</classname>s are kept in your program's memory
+ (the same applies to Cairo's <classname>ImageSurface</classname>).
+ Every time your program calls
+ <function>gdk_cairo_set_source_pixbuf</function>, that image needs to be
+ copied over to the video card and then painted onto your target surface.
+ If this needs to happen every time your window is exposed, it can cause
+ a significant performance penalty (especially over systems like remote
+ X11).
+ </para>
+
+ <para>
+ The solution is to create a working surface of the same type as the
+ target surface at the size of the image.
+ Many Cairo backends allow for fast painting between
+ surfaces of the same type (in graphics this is known as
+ <emphasis>blitting</emphasis>).
+ </para>
+
+ <para>
+ Create a working surface with
+ <function>cairo_surface_create_similar</function>.
+ Paint the image into the new surface. You can then
+ use this working surface as the source for further painting options
+ (<xref linkend="example.cairo.images.ex2"/>).
+ </para>
+
+ <example id="example.cairo.images.ex2">
+ <title>Faster painting of a theme icon</title>
+ <programlisting>
+<![CDATA[static cairo_surface_t *icon_surface = NULL;
+if (icon_surface == NULL)
+{
+ /* create the work surface */
+
+ GdkPixbuf *icon = gtk_icon_theme_load_icon (
+ gtk_icon_theme_get_default (),
+ GTK_STOCK_DIALOG_INFO, 48,
+ GTK_ICON_LOOKUP_USE_BUILTIN,
+ NULL);
+
+ cairo_surface_t *other_surface = cairo_get_target (cr);
+
+ icon_surface = cairo_surface_create_similar (target_surface,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ gdk_pixbuf_get_width (icon),
+ gdk_pixbuf_get_height (icon));
+ cairo_t *crw = cairo_create (icon_surface);
+
+ /* apply any common rotation or scaling here to cache it */
+ gdk_cairo_set_source_pixbuf (crw, icon, 0., 0.);
+ cairo_paint (crw);
+
+ cairo_destroy (crw);
+ g_object_unref (icon);
+}
+
+cairo_save (cr);
+
+/* position the image on the target surface */
+cairo_translate (cr, x, y);
+
+/* apply any specific rotation or scaling here */
+
+cairo_set_source_surface (cr, icon_surface, 0., 0.);
+cairo_paint (cr);
+
+cairo_restore (cr);]]></programlisting>
+ </example>
+
+ <para>
+ Don't forget to free <varname>icon_surface</varname> when it can no
+ longer be needed (e.g. when the <classname>GtkDrawingArea</classname> is
+ destroyed.
+ </para>
+
+ </sect2>
+
+ <sect2 id="sect.cairo.images.svg">
+ <title>Drawing SVG to a Cairo Surface</title>
+ </sect2>
+
+ </sect1>
</chapter>
Modified: trunk/gtk-drawing/C/gtk-drawing.xml
==============================================================================
--- trunk/gtk-drawing/C/gtk-drawing.xml (original)
+++ trunk/gtk-drawing/C/gtk-drawing.xml Thu Dec 18 10:32:16 2008
@@ -57,6 +57,7 @@
<xi:include href="introduction.xml"/>
<xi:include href="gtkdrawingarea.xml"/>
<xi:include href="goocanvas.xml"/>
- <xi:include href="cairo-pango.xml"/>
+ <xi:include href="cairo.xml"/>
+ <xi:include href="pango.xml"/>
</book>
Modified: trunk/gtk-drawing/C/gtkdrawingarea.xml
==============================================================================
--- trunk/gtk-drawing/C/gtkdrawingarea.xml (original)
+++ trunk/gtk-drawing/C/gtkdrawingarea.xml Thu Dec 18 10:32:16 2008
@@ -160,7 +160,7 @@
<para>
Details on drawing with Cairo can be found in
- <xref linkend="sect.cairo"/>.
+ <xref linkend="chapter.cairo"/>.
</para>
</sect2>
Added: trunk/gtk-drawing/C/pango.xml
==============================================================================
--- (empty file)
+++ trunk/gtk-drawing/C/pango.xml Thu Dec 18 10:32:16 2008
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+]>
+
+<chapter id="chapter.pango">
+ <title>Pango</title>
+
+</chapter>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]