[PATCH] tutorial: add program to generate the layer diagrams
Nis Martensen
nis.martensen at web.de
Tue Aug 21 02:22:24 PDT 2007
---
src/tutorial/diagram.c | 464 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 464 insertions(+), 0 deletions(-)
create mode 100644 src/tutorial/diagram.c
diff --git a/src/tutorial/diagram.c b/src/tutorial/diagram.c
new file mode 100644
index 0000000..c9cb004
--- /dev/null
+++ b/src/tutorial/diagram.c
@@ -0,0 +1,464 @@
+/*
+ * diagram.c draws the layer diagrams as part of the the cairo tutorial
+ * Copyright (C) 2007 Nis Martensen
+ * Derived from diagram.py
+ * <http://www.tortall.net/mu/wiki/CairoTutorial/diagram.py?raw>
+ * Copyright (C) 2006-2007 Michael Urman
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <string.h>
+#include <cairo.h>
+#include <cairo-svg.h>
+
+void diagram (char *name, double *alpha);
+void draw_source (char *name, cairo_t *cr);
+void draw_mask (char *name, cairo_t *cr);
+void draw_dest (char *name, cairo_t *cr);
+void diagram_draw_source (cairo_t *cr);
+void diagram_draw_mask (cairo_t *cr);
+void diagram_draw_mask_pattern (cairo_t *cr, cairo_pattern_t *pat);
+void diagram_draw_dest (cairo_t *cr);
+void stroke_draw_mask (cairo_t *cr);
+void stroke_draw_dest (cairo_t *cr);
+void fill_draw_mask (cairo_t *cr);
+void fill_draw_dest (cairo_t *cr);
+void showtext_draw_mask (cairo_t *cr);
+void showtext_draw_dest (cairo_t *cr);
+void paint_draw_source (cairo_t *cr);
+void paint_draw_dest (cairo_t *cr);
+void mask_draw_source (cairo_t *cr);
+void mask_draw_mask (cairo_t *cr);
+void mask_draw_dest (cairo_t *cr);
+
+int main ()
+{
+ double alpha[3];
+
+ alpha[0]=1.0; alpha[1]=0.15; alpha[2]=0.15;
+ diagram ("destination", alpha);
+
+ alpha[0]=0.15; alpha[1]=1.0; alpha[2]=0.15;
+ diagram ("the-mask", alpha);
+
+ alpha[0]=0.15; alpha[1]=0.15; alpha[2]=1.0;
+ diagram ("source", alpha);
+
+ alpha[0]=1.0; alpha[1]=0.8; alpha[2]=0.4;
+ diagram ("stroke", alpha);
+
+ alpha[0]=1.0; alpha[1]=0.8; alpha[2]=0.4;
+ diagram ("fill", alpha);
+
+ alpha[0]=1.0; alpha[1]=0.8; alpha[2]=0.4;
+ diagram ("showtext", alpha);
+
+ alpha[0]=1.0; alpha[1]=0.8; alpha[2]=0.4;
+ diagram ("paint", alpha);
+
+ alpha[0]=1.0; alpha[1]=0.8; alpha[2]=0.4;
+ diagram ("mask", alpha);
+
+ return 0;
+}
+
+void diagram (char *name, double *alpha)
+{
+ cairo_surface_t *surf;
+ cairo_t *cr;
+ cairo_matrix_t mat;
+
+ double width=160, height=120;
+ double ux=2, uy=2;
+
+ char svg_filename[50];
+ char png_filename[50];
+ strcpy (svg_filename, name);
+ strcpy (png_filename, name);
+ strcat (svg_filename, ".svg");
+ strcat (png_filename, ".png");
+
+ surf = cairo_svg_surface_create (svg_filename, width, height);
+ cr = cairo_create (surf);
+
+ /*
+ * show layers separately on the right
+ */
+ cairo_save (cr);
+ cairo_scale (cr, height/3, height/3);
+ cairo_translate (cr, 3*width/height-1, 0);
+ /* source */
+ cairo_save (cr);
+ cairo_push_group (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_clip (cr);
+ draw_source (name, cr);
+ cairo_pop_group_to_source (cr);
+ cairo_paint (cr);
+ cairo_restore (cr);
+ /* mask */
+ cairo_translate (cr, 0, 1);
+ cairo_save (cr);
+ cairo_push_group (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_clip (cr);
+ draw_mask (name, cr);
+ cairo_pop_group_to_source (cr);
+ cairo_paint (cr);
+ cairo_restore (cr);
+ /* destination */
+ cairo_translate (cr, 0, 1);
+ cairo_save (cr);
+ cairo_push_group (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_clip (cr);
+ draw_dest (name, cr);
+ cairo_pop_group_to_source (cr);
+ cairo_paint (cr);
+ cairo_restore (cr);
+ cairo_restore (cr);
+
+ /* draw a border around the layers */
+ cairo_save (cr);
+ cairo_scale (cr, height/3, height/3);
+ cairo_translate (cr, 3*width/height-1, 0);
+ cairo_device_to_user_distance (cr, &ux, &uy);
+ if (ux < uy)
+ ux = uy;
+ cairo_set_line_width (cr, ux);
+ cairo_rectangle (cr, 0, 0, 1, 3);
+ cairo_clip_preserve (cr);
+ cairo_stroke (cr);
+ cairo_rectangle (cr, 0, 1, 1, 1);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ /*
+ * layer diagram on the left
+ */
+
+ /* destination layer */
+ cairo_save (cr);
+ cairo_scale (cr, width-height/3, height);
+ cairo_matrix_init (&mat, 0.6, 0, 1.0/3, 0.5, 0.02, 0.45);
+ cairo_transform (cr, &mat);
+ cairo_push_group (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_clip (cr);
+ draw_dest (name, cr);
+ /* this layer gets a black border */
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ ux = 2; uy = 2;
+ cairo_device_to_user_distance (cr, &ux, &uy);
+ if (ux < uy)
+ ux = uy;
+ cairo_set_line_width (cr, ux);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_stroke (cr);
+ cairo_pop_group_to_source (cr);
+ cairo_paint_with_alpha (cr, alpha[0]);
+ cairo_restore (cr);
+
+ /* mask layer */
+ cairo_save (cr);
+ cairo_scale (cr, width-height/3, height);
+ cairo_matrix_init (&mat, 0.6, 0, 1.0/3, 0.5, 0.04, 0.25);
+ cairo_transform (cr, &mat);
+ cairo_push_group (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_clip (cr);
+ draw_mask (name, cr);
+ cairo_pop_group_to_source (cr);
+ cairo_paint_with_alpha (cr, alpha[1]);
+ cairo_restore (cr);
+
+ /* source layer */
+ cairo_save (cr);
+ cairo_scale (cr, width-height/3, height);
+ cairo_matrix_init (&mat, 0.6, 0, 1.0/3, 0.5, 0.06, 0.05);
+ cairo_transform (cr, &mat);
+ cairo_push_group (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_clip (cr);
+ draw_source (name, cr);
+ cairo_pop_group_to_source (cr);
+ cairo_paint_with_alpha (cr, alpha[2]);
+ cairo_restore (cr);
+
+ /* write output and clean up */
+ cairo_surface_write_to_png (surf, png_filename);
+ cairo_destroy (cr);
+ cairo_surface_destroy (surf);
+}
+
+void draw_source (char *name, cairo_t *cr)
+{
+ if (strcmp (name, "paint") == 0) {
+ paint_draw_source (cr);
+ } else if (strcmp (name, "mask") == 0) {
+ mask_draw_source (cr);
+ } else {
+ diagram_draw_source (cr);
+ }
+}
+
+void draw_mask (char *name, cairo_t *cr)
+{
+ if (strcmp (name, "stroke") == 0) {
+ stroke_draw_mask (cr);
+ } else if (strcmp (name, "fill") == 0) {
+ fill_draw_mask (cr);
+ } else if (strcmp (name, "showtext") == 0) {
+ showtext_draw_mask (cr);
+ } else if (strcmp (name, "paint") == 0) {
+ } else if (strcmp (name, "mask") == 0) {
+ mask_draw_mask (cr);
+ } else {
+ diagram_draw_mask (cr);
+ }
+}
+void draw_dest (char *name, cairo_t *cr)
+{
+ if (strcmp(name, "stroke") == 0) {
+ stroke_draw_dest (cr);
+ } else if (strcmp(name, "fill") == 0) {
+ fill_draw_dest (cr);
+ } else if (strcmp(name, "showtext") == 0) {
+ showtext_draw_dest (cr);
+ } else if (strcmp(name, "paint") == 0) {
+ paint_draw_dest (cr);
+ } else if (strcmp(name, "mask") == 0) {
+ mask_draw_dest (cr);
+ } else {
+ diagram_draw_dest (cr);
+ }
+}
+
+void diagram_draw_source (cairo_t *cr)
+{
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_fill (cr);
+}
+
+void diagram_draw_mask (cairo_t *cr)
+{
+ cairo_set_source_rgb (cr, 1, 0.9, 0.6);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_fill (cr);
+}
+
+void diagram_draw_mask_pattern (cairo_t *cr, cairo_pattern_t *pat)
+{
+ cairo_set_source_rgb (cr, 1, 0.9, 0.6);
+ cairo_mask (cr, pat);
+}
+
+void diagram_draw_dest (cairo_t *cr)
+{
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_fill (cr);
+}
+
+void stroke_draw_mask (cairo_t *cr)
+{
+ double px=1, py=1;
+ cairo_pattern_t *pat;
+
+ cairo_push_group (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_rectangle (cr, 0.20, 0.20, 0.6, 0.6);
+ cairo_rectangle (cr, 0.30, 0.30, 0.4, 0.4);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_fill (cr);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
+
+ pat = cairo_pop_group (cr);
+
+ diagram_draw_mask_pattern (cr, pat);
+
+ cairo_rectangle (cr, 0.25, 0.25, 0.5, 0.5);
+ cairo_set_source_rgb (cr, 0, 0.6, 0);
+
+ cairo_device_to_user_distance (cr, &px, &py);
+ if (px < py)
+ px = py;
+ cairo_set_line_width (cr, px);
+ cairo_stroke (cr);
+}
+
+void stroke_draw_dest (cairo_t *cr)
+{
+ diagram_draw_dest (cr);
+
+ cairo_set_line_width (cr, 0.1);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_rectangle (cr, 0.25, 0.25, 0.5, 0.5);
+ cairo_stroke (cr);
+}
+
+void fill_draw_mask (cairo_t *cr)
+{
+ double px=1, py=1;
+ cairo_pattern_t *pat;
+
+ cairo_push_group (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_rectangle (cr, 0.25, 0.25, 0.5, 0.5);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_fill (cr);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
+ pat = cairo_pop_group (cr);
+
+ diagram_draw_mask_pattern (cr, pat);
+
+ cairo_rectangle (cr, 0.25, 0.25, 0.5, 0.5);
+ cairo_set_source_rgb (cr, 0, 0.6, 0);
+ cairo_device_to_user_distance (cr, &px, &py);
+ if (px < py)
+ px = py;
+ cairo_set_line_width (cr, px);
+ cairo_stroke (cr);
+}
+
+void fill_draw_dest (cairo_t *cr)
+{
+ diagram_draw_dest (cr);
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_rectangle (cr, 0.25, 0.25, 0.5, 0.5);
+ cairo_fill (cr);
+}
+
+void showtext_draw_mask (cairo_t *cr)
+{
+ cairo_text_extents_t te;
+ double ux=1, uy=1;
+
+ /* yellow mask color */
+ cairo_set_source_rgb (cr, 1, 0.9, 0.6);
+
+ /* rectangle with an "a"-shaped hole */
+ cairo_select_font_face (cr, "Georgia",
+ CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size (cr, 1.2);
+ cairo_text_extents (cr, "a", &te);
+
+ cairo_push_group (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_move_to (cr, 0.5 - te.width / 2 - te.x_bearing,
+ 0.5 - te.height / 2 - te.y_bearing);
+ cairo_text_path (cr, "a");
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_fill (cr);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
+ cairo_pop_group_to_source (cr);
+ cairo_paint (cr);
+
+ /* show the outline of the glyph with a green line */
+ cairo_move_to (cr, 0.5 - te.width / 2 - te.x_bearing,
+ 0.5 - te.height / 2 - te.y_bearing);
+ cairo_set_source_rgb (cr, 0, 0.6, 0);
+
+ cairo_device_to_user_distance (cr, &ux, &uy);
+ if (ux < uy)
+ ux = uy;
+ cairo_set_line_width (cr, ux);
+
+ cairo_text_path (cr, "a");
+ cairo_stroke (cr);
+}
+
+void showtext_draw_dest (cairo_t *cr)
+{
+ cairo_text_extents_t te;
+
+ /* white background */
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_fill (cr);
+
+ /* black letter "a" */
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+ cairo_select_font_face (cr, "Georgia",
+ CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size (cr, 1.2);
+ cairo_text_extents (cr, "a", &te);
+ 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");
+}
+
+void paint_draw_source (cairo_t *cr)
+{
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_fill (cr);
+}
+
+void paint_draw_dest (cairo_t *cr)
+{
+ diagram_draw_dest (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint_with_alpha (cr, 0.5);
+}
+
+void mask_draw_source (cairo_t *cr)
+{
+ cairo_pattern_t *linpat;
+
+ linpat = cairo_pattern_create_linear (0, 0, 1, 1);
+ cairo_pattern_add_color_stop_rgb (linpat, 0, 0, 0.3, 0.8);
+ cairo_pattern_add_color_stop_rgb (linpat, 1, 0, 0.8, 0.3);
+
+ cairo_set_source (cr, linpat);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_fill (cr);
+}
+
+void mask_draw_mask (cairo_t *cr)
+{
+ cairo_pattern_t *radialinv;
+
+ radialinv = cairo_pattern_create_radial (0.5, 0.5, 0.25, 0.5, 0.5, 0.5);
+ cairo_pattern_add_color_stop_rgba (radialinv, 0, 0, 0, 0, 0);
+ cairo_pattern_add_color_stop_rgba (radialinv, 0.5, 0, 0, 0, 1);
+
+ cairo_save (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_clip (cr);
+ diagram_draw_mask_pattern (cr, radialinv);
+ cairo_restore (cr);
+}
+
+void mask_draw_dest (cairo_t *cr)
+{
+ cairo_pattern_t *linpat, *radpat;
+ linpat = cairo_pattern_create_linear (0, 0, 1, 1);
+ cairo_pattern_add_color_stop_rgb (linpat, 0, 0, 0.3, 0.8);
+ cairo_pattern_add_color_stop_rgb (linpat, 1, 0, 0.8, 0.3);
+
+ radpat = cairo_pattern_create_radial (0.5, 0.5, 0.25, 0.5, 0.5, 0.5);
+ cairo_pattern_add_color_stop_rgba (radpat, 0, 0, 0, 0, 1);
+ cairo_pattern_add_color_stop_rgba (radpat, 0.5, 0, 0, 0, 0);
+
+ diagram_draw_dest (cr);
+ cairo_save (cr);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_clip (cr);
+ cairo_set_source (cr, linpat);
+ cairo_mask (cr, radpat);
+ cairo_restore (cr);
+}
--
1.5.3.rc6.17.g1911
--HlL+5n6rz5pIUxbD
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="0002-add-a-link-to-the-diagram-code.patch"
More information about the cairo
mailing list