gnome-devel-docs r603 - in trunk/gtk-drawing: . C
- From: davyd svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-devel-docs r603 - in trunk/gtk-drawing: . C
- Date: Mon, 6 Oct 2008 10:05:53 +0000 (UTC)
Author: davyd
Date: Mon Oct 6 10:05:53 2008
New Revision: 603
URL: http://svn.gnome.org/viewvc/gnome-devel-docs?rev=603&view=rev
Log:
2008-10-06 Davyd Madeley <davyd fugro-fsi com au>
* C/cairo-pango.xml:
- a whole chunk on masking
Modified:
trunk/gtk-drawing/C/cairo-pango.xml
trunk/gtk-drawing/ChangeLog
Modified: trunk/gtk-drawing/C/cairo-pango.xml
==============================================================================
--- trunk/gtk-drawing/C/cairo-pango.xml (original)
+++ trunk/gtk-drawing/C/cairo-pango.xml Mon Oct 6 10:05:53 2008
@@ -8,6 +8,158 @@
<sect1 id="sect.cairo">
<title>Cairo</title>
+
+ <sect2 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>
+
+ </sect2>
</sect1>
<sect1 id="sect.pango">
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]