[cairo-commit] 3 commits - src/cairo-debug.c test/a1-sample.c test/a1-sample.ref.png test/Makefile.refs test/Makefile.sources test/unclosed-strokes.c test/unclosed-strokes.ref.png util/Makefile.am util/show-polygon.c

Chris Wilson ickle at kemper.freedesktop.org
Sun Aug 7 01:03:01 PDT 2011


 src/cairo-debug.c             |    3 
 test/Makefile.refs            |    2 
 test/Makefile.sources         |    4 
 test/a1-sample.c              |   59 ++++
 test/a1-sample.ref.png        |binary
 test/unclosed-strokes.c       |   83 ++++++
 test/unclosed-strokes.ref.png |binary
 util/Makefile.am              |    7 
 util/show-polygon.c           |  560 ++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 715 insertions(+), 3 deletions(-)

New commits:
commit 4236821d11407eb4af5a02bac78aff1fc19be017
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Aug 6 22:40:32 2011 +0100

    test: Add unclosed-strokes
    
    Checks that coincident end-points are not converted to joins. It briefly
    passed through my mind that was a good thing...
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/Makefile.refs b/test/Makefile.refs
index 5926b5f..ac5194d 100644
--- a/test/Makefile.refs
+++ b/test/Makefile.refs
@@ -1357,6 +1357,7 @@ REFERENCE_IMAGES = \
 	unbounded-operator.svg12.argb32.ref.png \
 	unbounded-operator.svg12.rgb24.xfail.png \
 	unbounded-operator.xlib.rgb24.ref.png \
+	unclosed-strokes.ref.png \
 	user-font-mask.image16.ref.png \
 	user-font-mask.pdf.ref.png \
 	user-font-mask.ps2.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
index ed5d732..846d67b 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -307,9 +307,10 @@ test_sources = \
 	twin-antialias-mixed.c				\
 	twin-antialias-none.c				\
 	twin-antialias-subpixel.c			\
-	unaligned-box.c				\
+	unaligned-box.c					\
 	unantialiased-shapes.c				\
 	unbounded-operator.c				\
+	unclosed-strokes.c				\
 	user-data.c					\
 	user-font.c					\
 	user-font-mask.c				\
diff --git a/test/unclosed-strokes.c b/test/unclosed-strokes.c
new file mode 100644
index 0000000..3c0287f
--- /dev/null
+++ b/test/unclosed-strokes.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+#define LINE_WIDTH	10.
+#define SIZE		(5 * LINE_WIDTH)
+#define PAD		(2 * LINE_WIDTH)
+
+static void
+make_path (cairo_t *cr)
+{
+    cairo_move_to (cr, 0, 0);
+    cairo_rel_line_to (cr, -SIZE/2, SIZE);
+    cairo_rel_line_to (cr, SIZE, 0);
+    /* back to the start, but do not close */
+    cairo_rel_line_to (cr, -SIZE/2, -SIZE);
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_save (cr);
+    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+    cairo_paint (cr);
+    cairo_restore (cr);
+
+    cairo_set_line_width (cr, LINE_WIDTH);
+    cairo_translate (cr, PAD + SIZE / 2., PAD);
+
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_BEVEL);
+    make_path (cr);
+    cairo_stroke (cr);
+
+    cairo_translate (cr, 0, SIZE + PAD);
+
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+    make_path (cr);
+    cairo_stroke (cr);
+
+    cairo_translate (cr, 0, SIZE + PAD);
+
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+    make_path (cr);
+    cairo_stroke (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (unclosed_strokes,
+	    "Test coincident end-points are capped and not joined",
+	    "stroke caps", /* keywords */
+	    NULL, /* requirements */
+	    PAD + SIZE + PAD,
+	    3 * (PAD + SIZE) + PAD,
+	    NULL, draw)
+
diff --git a/test/unclosed-strokes.ref.png b/test/unclosed-strokes.ref.png
new file mode 100644
index 0000000..e42d065
Binary files /dev/null and b/test/unclosed-strokes.ref.png differ
commit 37e1a1b3ed8ab698d5b58573e1c6a25edc3f1cde
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Aug 6 22:32:47 2011 +0100

    test: Add a1-sample
    
    Ensures that only a box that covers the centre pixel is filled with
    antialiasing disabled.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/Makefile.refs b/test/Makefile.refs
index 6eaf1cc..5926b5f 100644
--- a/test/Makefile.refs
+++ b/test/Makefile.refs
@@ -17,6 +17,7 @@ REFERENCE_IMAGES = \
 	a1-rasterisation-rectangles.ref.png \
 	a1-rasterisation-triangles.quartz.xfail.png \
 	a1-rasterisation-triangles.ref.png \
+	a1-sample.ref.png \
 	a1-traps-sample.quartz.xfail.png \
 	a1-traps-sample.ref.png \
 	a8-clear.quartz.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 68f075f..ed5d732 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -4,6 +4,7 @@ test_sources = \
 	a1-image-sample.c 				\
 	a1-mask.c					\
 	a1-mask-sample.c 				\
+	a1-sample.c	 				\
 	a1-traps-sample.c				\
 	a1-rasterisation.c				\
 	a8-clear.c					\
diff --git a/test/a1-sample.c b/test/a1-sample.c
new file mode 100644
index 0000000..977dfc8
--- /dev/null
+++ b/test/a1-sample.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+#define WIDTH	(256) //CAIRO_FIXED_ONE
+#define HEIGHT	(WIDTH)
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    int i, j;
+
+    /* Fill background white */
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_paint (cr);
+
+    cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+    cairo_set_source_rgb (cr, 0, 0, 0);
+
+    /* Only the single rectangle that covers the centre pixel should be filled*/
+    for (i = 0; i < 256; i++)
+	for (j = 0; j < 256; j++) {
+	    cairo_rectangle (cr, i + i/256., j + j/256., 1/256., 1/256.);
+	    cairo_fill (cr);
+	}
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (a1_sample,
+	    "Tests unantialiased rendering of a quantum box",
+	    " alpha", /* keywords */
+	    "target=raster", /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/a1-sample.ref.png b/test/a1-sample.ref.png
new file mode 100644
index 0000000..4c6131c
Binary files /dev/null and b/test/a1-sample.ref.png differ
commit 307cb2a9738374f31d2900e62103524fdf27df42
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Aug 7 09:00:56 2011 +0100

    util: Add show-polygons
    
    Another variant of the utility apps that understand the output of
    _cairo_debug_print_polygon().
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 9e68748..ada0cdb 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -283,7 +283,8 @@ _cairo_debug_print_polygon (FILE *stream, cairo_polygon_t *polygon)
 	cairo_edge_t *edge = &polygon->edges[n];
 
 	fprintf (stream,
-		 "  (%f, %f) -> (%f, %f), top=%f, bottom=%f, dir=%d\n",
+		 "  [%d] = [(%f, %f), (%f, %f)], top=%f, bottom=%f, dir=%d\n",
+		 n,
 		 _cairo_fixed_to_double (edge->line.p1.x),
 		 _cairo_fixed_to_double (edge->line.p1.y),
 		 _cairo_fixed_to_double (edge->line.p2.x),
diff --git a/util/Makefile.am b/util/Makefile.am
index dc13abd..f3aa079 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -32,7 +32,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src \
 	      -I$(top_srcdir)/util/cairo-script	\
 	      $(CAIRO_CFLAGS)
 
-EXTRA_PROGRAMS += show-traps show-edges show-events
+EXTRA_PROGRAMS += show-traps show-edges show-polygon show-events
 if CAIRO_HAS_INTERPRETER
 EXTRA_PROGRAMS += trace-to-xml xml-to-trace
 endif
@@ -46,6 +46,11 @@ show_traps_CFLAGS = $(gtk_CFLAGS)
 #show_traps_LDADD = $(top_builddir)/src/libcairo.la $(gtk_LIBS)
 show_traps_LDADD = $(gtk_LIBS)
 
+show_polygon_SOURCES = show-polygon.c
+show_polygon_CFLAGS = $(gtk_CFLAGS)
+#show_polygon_LDADD = $(top_builddir)/src/libcairo.la $(gtk_LIBS)
+show_polygon_LDADD = $(gtk_LIBS)
+
 show_edges_SOURCES = show-edges.c
 show_edges_CFLAGS = $(gtk_CFLAGS)
 #show_edges_LDADD = $(top_builddir)/src/libcairo.la $(gtk_LIBS)
diff --git a/util/show-polygon.c b/util/show-polygon.c
new file mode 100644
index 0000000..7c9031c
--- /dev/null
+++ b/util/show-polygon.c
@@ -0,0 +1,560 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <gdk/gdkkeysyms.h>
+#include <math.h>
+
+typedef struct _point {
+    gdouble x, y;
+} point_t;
+typedef struct _edge {
+    point_t p1, p2;
+    gdouble top, bot;
+    int dir;
+} edge_t;
+typedef struct _box {
+    point_t p1, p2;
+} box_t;
+
+typedef struct _polygon {
+    struct _polygon *next, *prev;
+    int num_edges;
+    int size;
+    edge_t edges[0];
+} polygon_t;
+
+typedef struct _PolygonView {
+    GtkWidget widget;
+
+    cairo_surface_t *pixmap;
+    int pixmap_width, pixmap_height;
+
+    box_t extents;
+    polygon_t *polygons;
+
+    double px, py;
+
+    gint mag_x, mag_y;
+    gint mag_size;
+    gdouble mag_zoom;
+    gboolean in_mag_drag;
+    gint mag_drag_x, mag_drag_y;
+} PolygonView;
+
+typedef struct _PolygonViewClass {
+    GtkWidgetClass parent_class;
+} PolygonViewClass;
+
+G_DEFINE_TYPE (PolygonView, polygon_view, GTK_TYPE_WIDGET)
+
+static void draw_edges (cairo_t *cr, polygon_t *p, int dir)
+{
+    int n;
+
+    for (n = 0; n < p->num_edges; n++) {
+	const edge_t *e = &p->edges[n];
+
+	if (e->dir != dir)
+	    continue;
+
+	cairo_move_to (cr, e->p1.x, e->p1.y);
+	cairo_line_to (cr, e->p2.x, e->p2.y);
+    }
+    cairo_save (cr); {
+	cairo_identity_matrix (cr);
+	cairo_set_line_width (cr, 1.);
+	cairo_stroke (cr);
+    } cairo_restore (cr);
+}
+
+static void draw_polygon (cairo_t *cr, polygon_t *p)
+{
+    cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
+    draw_edges (cr, p, -1);
+
+    cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
+    draw_edges (cr, p, +1);
+}
+
+static cairo_surface_t *
+pixmap_create (PolygonView *self, cairo_surface_t *target)
+{
+    cairo_surface_t *surface =
+	cairo_surface_create_similar (target, CAIRO_CONTENT_COLOR,
+				      self->widget.allocation.width,
+				      self->widget.allocation.height);
+    cairo_t *cr = cairo_create (surface);
+    polygon_t *polygon;
+    gdouble sf_x, sf_y, sf;
+    gdouble mid, dim;
+    gdouble x0,  y0;
+    box_t extents;
+
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_paint (cr);
+
+    if (self->polygons == NULL) {
+	cairo_destroy(cr);
+	return surface;
+    }
+
+    extents = self->extents;
+
+    mid = (extents.p2.x + extents.p1.x) / 2.;
+    dim = (extents.p2.x - extents.p1.x) / 2. * 1.25;
+    sf_x = self->widget.allocation.width / dim / 2;
+
+    mid = (extents.p2.y + extents.p1.y) / 2.;
+    dim = (extents.p2.y - extents.p1.y) / 2. * 1.25;
+    sf_y = self->widget.allocation.height / dim / 2;
+
+    sf = MIN (sf_x, sf_y);
+
+    mid = (extents.p2.x + extents.p1.x) / 2.;
+    dim = sf_x / sf * (extents.p2.x - extents.p1.x) / 2. * 1.25;
+    x0 = mid - dim;
+    mid = (extents.p2.y + extents.p1.y) / 2.;
+    dim = sf_y / sf * (extents.p2.y - extents.p1.y) / 2. * 1.25;
+    y0 = mid - dim;
+
+    cairo_save (cr); {
+	cairo_scale (cr, sf, sf);
+	cairo_translate (cr, -x0, -y0);
+
+	for (polygon = self->polygons; polygon; polygon = polygon->next) {
+	    if (polygon->num_edges == 0)
+		continue;
+
+	    draw_polygon (cr, polygon);
+	}
+    } cairo_restore (cr);
+
+    cairo_destroy (cr);
+    return surface;
+}
+
+static void
+polygon_view_draw (PolygonView *self, cairo_t *cr)
+{
+    polygon_t *polygon;
+    gdouble sf_x, sf_y, sf;
+    gdouble mid, dim;
+    gdouble x0,  y0;
+    box_t extents;
+
+    extents = self->extents;
+
+    mid = (extents.p2.x + extents.p1.x) / 2.;
+    dim = (extents.p2.x - extents.p1.x) / 2. * 1.25;
+    sf_x = self->widget.allocation.width / dim / 2;
+
+    mid = (extents.p2.y + extents.p1.y) / 2.;
+    dim = (extents.p2.y - extents.p1.y) / 2. * 1.25;
+    sf_y = self->widget.allocation.height / dim / 2;
+
+    sf = MIN (sf_x, sf_y);
+
+    mid = (extents.p2.x + extents.p1.x) / 2.;
+    dim = sf_x / sf * (extents.p2.x - extents.p1.x) / 2. * 1.25;
+    x0 = mid - dim;
+    mid = (extents.p2.y + extents.p1.y) / 2.;
+    dim = sf_y / sf * (extents.p2.y - extents.p1.y) / 2. * 1.25;
+    y0 = mid - dim;
+
+    if (self->pixmap_width != self->widget.allocation.width ||
+	self->pixmap_height != self->widget.allocation.height)
+    {
+	cairo_surface_destroy (self->pixmap);
+	self->pixmap = pixmap_create (self, cairo_get_target (cr));
+	self->pixmap_width = self->widget.allocation.width;
+	self->pixmap_height = self->widget.allocation.height;
+    }
+
+    cairo_set_source_surface (cr, self->pixmap, 0, 0);
+    cairo_paint (cr);
+
+    if (self->polygons == NULL)
+	return;
+
+    /* draw a zoom view of the area around the mouse */
+    if (1) {
+	double zoom = self->mag_zoom;
+	int size = self->mag_size;
+	int mag_x = self->mag_x;
+	int mag_y = self->mag_y;
+
+	if (1) {
+	    if (self->px + size < self->widget.allocation.width/2)
+		mag_x = self->px + size/4;
+	    else
+		mag_x = self->px - size/4 - size;
+	    mag_y = self->py - size/2;
+	}
+
+	cairo_save (cr); {
+	    /* bottom right */
+	    cairo_rectangle (cr, mag_x, mag_y, size, size);
+	    cairo_stroke_preserve (cr);
+	    cairo_set_source_rgb (cr, 1, 1, 1);
+	    cairo_fill_preserve (cr);
+	    cairo_clip (cr);
+
+	    /* compute roi in extents */
+	    cairo_translate (cr, mag_x + size/2, mag_y + size/2);
+
+	    cairo_save (cr); {
+		cairo_scale (cr, zoom, zoom);
+		cairo_translate (cr, -(self->px / sf + x0), -(self->py /sf + y0));
+		for (polygon = self->polygons; polygon; polygon = polygon->next) {
+		    if (polygon->num_edges == 0)
+			continue;
+
+		    draw_polygon (cr, polygon);
+		}
+	    } cairo_restore (cr);
+
+	    /* grid */
+	    cairo_save (cr); {
+		int i;
+
+		cairo_translate (cr,
+				 -zoom*fmod (self->px/sf + x0, 1.),
+				 -zoom*fmod (self->py/sf + y0, 1.));
+		zoom /= 2;
+		for (i = -size/2/zoom; i <= size/2/zoom + 1; i+=2) {
+		    cairo_move_to (cr, zoom*i, -size/2);
+		    cairo_line_to (cr, zoom*i, size/2 + zoom);
+		    cairo_move_to (cr, -size/2, zoom*i);
+		    cairo_line_to (cr, size/2 + zoom, zoom*i);
+		}
+		zoom *= 2;
+		cairo_set_source_rgba (cr, .7, .7, .7, .5);
+		cairo_set_line_width (cr, 1.);
+		cairo_stroke (cr);
+
+		for (i = -size/2/zoom - 1; i <= size/2/zoom + 1; i++) {
+		    cairo_move_to (cr, zoom*i, -size/2);
+		    cairo_line_to (cr, zoom*i, size/2 + zoom);
+		    cairo_move_to (cr, -size/2, zoom*i);
+		    cairo_line_to (cr, size/2 + zoom, zoom*i);
+		}
+		cairo_set_source_rgba (cr, .1, .1, .1, .5);
+		cairo_set_line_width (cr, 2.);
+		cairo_stroke (cr);
+	    } cairo_restore (cr);
+
+	} cairo_restore (cr);
+    }
+}
+
+static gboolean
+polygon_view_expose (GtkWidget *w, GdkEventExpose *ev)
+{
+    PolygonView *self = (PolygonView *) w;
+    cairo_t *cr;
+
+    cr = gdk_cairo_create (w->window);
+    gdk_cairo_region (cr, ev->region);
+    cairo_clip (cr);
+
+    polygon_view_draw (self, cr);
+
+    cairo_destroy (cr);
+    return FALSE;
+}
+
+static gboolean
+polygon_view_key_press (GtkWidget *w, GdkEventKey *ev)
+{
+    switch (ev->keyval) {
+    case GDK_Escape:
+    case GDK_Q:
+	gtk_main_quit ();
+	break;
+    }
+
+    return FALSE;
+}
+
+static gboolean
+polygon_view_button_press (GtkWidget *w, GdkEventButton *ev)
+{
+    PolygonView *self = (PolygonView *) w;
+
+    if (ev->x < self->mag_x ||
+	ev->y < self->mag_y ||
+	ev->x > self->mag_x + self->mag_size ||
+	ev->y > self->mag_y + self->mag_size)
+    {
+    }
+    else
+    {
+	self->in_mag_drag = TRUE;
+	self->mag_drag_x = ev->x;
+	self->mag_drag_y = ev->y;
+    }
+
+    return FALSE;
+}
+
+static gboolean
+polygon_view_button_release (GtkWidget *w, GdkEventButton *ev)
+{
+    PolygonView *self = (PolygonView *) w;
+
+    self->in_mag_drag = FALSE;
+
+    return FALSE;
+}
+
+static void
+polygon_view_update_mouse (PolygonView *self, GdkEventMotion *ev)
+{
+    self->px = ev->x;
+    self->py = ev->y;
+
+    gtk_widget_queue_draw (&self->widget);
+}
+
+static void
+polygon_view_update_magnifier (PolygonView *self, gint *xy)
+{
+    self->mag_x = xy[0];
+    self->mag_y = xy[1];
+
+    gtk_widget_queue_draw (&self->widget);
+}
+
+static gboolean
+polygon_view_motion (GtkWidget *w, GdkEventMotion *ev)
+{
+    PolygonView *self = (PolygonView *) w;
+
+    if (self->in_mag_drag) {
+	int xy[2];
+
+	xy[0] = self->mag_x + ev->x - self->mag_drag_x;
+	xy[1] = self->mag_y + ev->y - self->mag_drag_y;
+
+	polygon_view_update_magnifier (self, xy);
+
+	self->mag_drag_x = ev->x;
+	self->mag_drag_y = ev->y;
+    } else if (ev->x < self->mag_x ||
+	       ev->y < self->mag_y ||
+	       ev->x > self->mag_x + self->mag_size ||
+	       ev->y > self->mag_y + self->mag_size)
+    {
+	polygon_view_update_mouse (self, ev);
+    }
+
+    return FALSE;
+}
+
+static void
+polygon_view_realize (GtkWidget *widget)
+{
+    GdkWindowAttr attributes;
+
+    GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+    attributes.window_type = GDK_WINDOW_CHILD;
+    attributes.x = widget->allocation.x;
+    attributes.y = widget->allocation.y;
+    attributes.width  = widget->allocation.width;
+    attributes.height = widget->allocation.height;
+    attributes.wclass = GDK_INPUT_OUTPUT;
+    attributes.visual = gtk_widget_get_visual (widget);
+    attributes.colormap = gtk_widget_get_colormap (widget);
+    attributes.event_mask = gtk_widget_get_events (widget) |
+	                    GDK_BUTTON_PRESS_MASK |
+	                    GDK_BUTTON_RELEASE_MASK |
+	                    GDK_KEY_PRESS_MASK |
+	                    GDK_KEY_RELEASE_MASK |
+			    GDK_POINTER_MOTION_MASK |
+			    GDK_BUTTON_MOTION_MASK |
+	                    GDK_EXPOSURE_MASK;
+
+    widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+				     &attributes,
+				     GDK_WA_X | GDK_WA_Y |
+				     GDK_WA_VISUAL | GDK_WA_COLORMAP);
+    gdk_window_set_user_data (widget->window, widget);
+
+    widget->style = gtk_style_attach (widget->style, widget->window);
+    gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+polygon_view_size_allocate (GtkWidget *w, GdkRectangle *r)
+{
+    PolygonView *self = (PolygonView *) w;
+
+    GTK_WIDGET_CLASS (polygon_view_parent_class)->size_allocate (w, r);
+
+    self->mag_x = w->allocation.width - self->mag_size - 10;
+    self->mag_y = w->allocation.height - self->mag_size - 10;
+}
+
+static void
+polygon_view_finalize (GObject *obj)
+{
+    G_OBJECT_CLASS (polygon_view_parent_class)->finalize (obj);
+}
+
+static void
+polygon_view_class_init (PolygonViewClass *klass)
+{
+    GObjectClass *object_class = (GObjectClass *) klass;
+    GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+
+    object_class->finalize = polygon_view_finalize;
+
+    widget_class->realize = polygon_view_realize;
+    widget_class->size_allocate = polygon_view_size_allocate;
+    widget_class->expose_event = polygon_view_expose;
+    widget_class->key_press_event = polygon_view_key_press;
+    widget_class->button_press_event = polygon_view_button_press;
+    widget_class->button_release_event = polygon_view_button_release;
+    widget_class->motion_notify_event = polygon_view_motion;
+}
+
+static void
+polygon_view_init (PolygonView *self)
+{
+    self->mag_zoom = 64;
+    self->mag_size = 200;
+
+    self->extents.p1.x = G_MAXDOUBLE;
+    self->extents.p1.y = G_MAXDOUBLE;
+    self->extents.p2.x = -G_MAXDOUBLE;
+    self->extents.p2.y = -G_MAXDOUBLE;
+
+    GTK_WIDGET_SET_FLAGS (self, GTK_CAN_FOCUS);
+}
+
+static polygon_t *
+_polygon_add_edge (PolygonView *view, polygon_t *polygon,
+		   point_t *p1, point_t *p2,
+		   gdouble top, gdouble bot, int dir)
+{
+    if (polygon == NULL)
+	return NULL;
+
+    if (top < view->extents.p1.y)
+	view->extents.p1.y = top;
+    if (bot > view->extents.p2.y)
+	view->extents.p2.y = bot;
+
+    if (p1->x < view->extents.p1.x)
+	view->extents.p1.x = p1->x;
+    if (p1->x > view->extents.p2.x)
+	view->extents.p2.x = p1->x;
+    if (p2->x < view->extents.p1.x)
+	view->extents.p1.x = p2->x;
+    if (p2->x > view->extents.p2.x)
+	view->extents.p2.x = p2->x;
+
+    if (polygon->num_edges == polygon->size) {
+	int newsize = 2 * polygon->size;
+	void *newpolygon;
+
+	newpolygon = g_realloc (polygon,
+			      sizeof (polygon_t) + newsize * sizeof (edge_t));
+	if (newpolygon == NULL)
+	    return polygon;
+
+	polygon = newpolygon;
+	polygon->size = newsize;
+
+	if (polygon->next != NULL)
+	    polygon->next->prev = newpolygon;
+	if (polygon->prev != NULL)
+	    polygon->prev->next = newpolygon;
+	else
+	    view->polygons = newpolygon;
+    }
+
+    polygon->edges[polygon->num_edges].p1 = *p1;
+    polygon->edges[polygon->num_edges].p2 = *p2;
+    polygon->edges[polygon->num_edges].top = top;
+    polygon->edges[polygon->num_edges].bot = bot;
+    polygon->edges[polygon->num_edges].dir = dir;
+    polygon->num_edges++;
+
+    return polygon;
+}
+
+static polygon_t *
+polygon_new (PolygonView *view)
+{
+    polygon_t *t;
+
+    t = g_malloc (sizeof (polygon_t) + 128 * sizeof (edge_t));
+    t->prev = NULL;
+    t->next = view->polygons;
+    if (view->polygons)
+	view->polygons->prev = t;
+    view->polygons = t;
+
+    t->size = 128;
+    t->num_edges = 0;
+
+    return t;
+}
+
+int
+main (int argc, char **argv)
+{
+    PolygonView *view;
+    polygon_t *polygon = NULL;
+    GtkWidget *window;
+    FILE *file;
+    char *line = NULL;
+    size_t len = 0;
+
+    gtk_init (&argc, &argv);
+
+    view = g_object_new (polygon_view_get_type (), NULL);
+
+    file = fopen (argv[1], "r");
+    if (file != NULL) {
+	while (getline (&line, &len, file) != -1) {
+	    point_t p1, p2;
+	    double top, bottom;
+	    int dir;
+
+	    if (strncmp (line, "polygon: ", sizeof("polygon: ")-1) == 0) {
+		if (polygon && polygon->num_edges) {
+		    g_print ("read polygon with %d edges\n", polygon->num_edges);
+
+		    polygon = polygon_new (view);
+		} else if (polygon == NULL)
+		    polygon = polygon_new (view);
+	    } else if (sscanf (line, "  [%*d] = [(%lf, %lf), (%lf, %lf)], top=%lf, bottom=%lf, dir=%d", &p1.x, &p1.y, &p2.x, &p2.y, &top, &bottom, &dir) == 7) {
+		polygon = _polygon_add_edge (view, polygon, &p1, &p2,
+					     top, bottom, dir);
+	    }
+	}
+
+	if (polygon && polygon->num_edges)
+	    g_print ("read polygon with %d edges\n", polygon->num_edges);
+
+	g_print ("extents=(%lg, %lg), (%lg, %lg)\n",
+		 view->extents.p1.x, view->extents.p1.y,
+		 view->extents.p2.x, view->extents.p2.y);
+	fclose (file);
+    }
+
+    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    g_signal_connect (window, "delete-event",
+		      G_CALLBACK (gtk_main_quit), NULL);
+    gtk_widget_set_size_request (window, 800, 800);
+    gtk_container_add (GTK_CONTAINER (window), &view->widget);
+    gtk_widget_show_all (window);
+
+    gtk_main ();
+    return 0;
+}


More information about the cairo-commit mailing list