summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--poly3.c228
1 files changed, 211 insertions, 17 deletions
diff --git a/poly3.c b/poly3.c
index 01a4ada..5705518 100644
--- a/poly3.c
+++ b/poly3.c
@@ -5,6 +5,45 @@
#include <string.h>
#include <assert.h>
#include <cairo.h>
+#include <gtk/gtk.h>
+
+
+/*
+ * The sample grid.
+ *
+ * Note that this starts breaking down if we go above 8 bits of
+ * alpha. For 10 bits of alpha, the sample grid becomes 31 x 33, the
+ * "small step" is 4 in the 24.8, and the big step is 8. The big is twice
+ * as big as the small step, so instead it would be better to alternate
+ * big steps and small steps; we can no longer put the whole big step
+ * at the end.
+
+ * If there are more samples than there is fixed-point resolution,
+ * then things break down completely. For example, with 16 bits of alpha,
+ * the sample grid is 255 x 257, so n that case, we really need more than
+ * 8 fractional bits. In the X direction, the small step would be 0, so we
+ * would get divide-by-zero errors.
+ *
+ * +--------------------------------------------------+
+ * | <Y_FRAC_FIRST> |
+ * | <X_FRAC_FIRST> * * * * * * * * * * * * * * * * * |\ SMALL_STEP_Y
+ * | * * * * * * * * * * * * * * * * * |/
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | * * * * * * * * * * * * * * * * * |
+ * | | <BIG_STEP_Y> |
+ * +--------------------------------------------------+
+ */
typedef int32_t fixed_t;
@@ -43,16 +82,18 @@ typedef int32_t fixed_t;
#define X_FRAC_FIRST(n) (STEP_X_SMALL(n) / 2)
#define X_FRAC_LAST(n) (X_FRAC_FIRST(n) + (N_X_FRAC(n) - 1) * STEP_X_SMALL(n))
-#define N_GRID_X N_X_FRAC(8)
-#define N_GRID_Y N_Y_FRAC(8)
+#define N_BITS 8
+
+#define N_GRID_X N_X_FRAC(N_BITS)
+#define N_GRID_Y N_Y_FRAC(N_BITS)
-#define BIG_STEP_Y STEP_Y_BIG(8)
-#define SMALL_STEP_Y STEP_Y_SMALL(8)
-#define FIRST_STEP_Y Y_FRAC_FIRST(8)
+#define BIG_STEP_Y STEP_Y_BIG(N_BITS)
+#define SMALL_STEP_Y STEP_Y_SMALL(N_BITS)
+#define FIRST_STEP_Y Y_FRAC_FIRST(N_BITS)
-#define BIG_STEP_X STEP_X_BIG(8)
-#define SMALL_STEP_X STEP_X_SMALL(8)
-#define FIRST_STEP_X X_FRAC_FIRST(8)
+#define BIG_STEP_X STEP_X_BIG(N_BITS)
+#define SMALL_STEP_X STEP_X_SMALL(N_BITS)
+#define FIRST_STEP_X X_FRAC_FIRST(N_BITS)
/* A "sample_t" is a fixed_t where the fractional bits are replaced with
* a small integer indicating the sample number in the pixel.
@@ -263,11 +304,13 @@ edge_init (edge_t *edge, sample_t first_yi)
{
int64_t dx, dy;
+#if 0
printf ("Activating (%f %f %f %f)\n",
fixed_to_double (top->x),
fixed_to_double (top->y),
fixed_to_double (bottom->x),
fixed_to_double (bottom->y));
+#endif
dx = (bottom->x - top->x);
dy = (bottom->y - top->y);
@@ -511,18 +554,48 @@ polygon_rasterize (polygon_t *polygon,
#define df(a) double_to_fixed(a)
+#define MULTIPLIER (375)
+
+static int last_y;
+static int last_x;
+static int p;
+
static void
emit (sample_t xi, sample_t yi, void *data)
{
- printf ("(%8x, %8x) => (%f, %f)\n",
- xi, yi,
- fixed_to_double (sample_to_pos_x (xi)),
- fixed_to_double (sample_to_pos_y (yi)));
+ cairo_t *cr = data;
+ double x = (MULTIPLIER * fixed_to_double (sample_to_pos_x (xi)));
+ double y = (MULTIPLIER * fixed_to_double (sample_to_pos_y (yi)));
+
+#if 0
+ printf ("point: %f %f\n", x, y);
+#endif
+
+ cairo_set_source_rgba (cr, 0.4, 0.8, 0.4, 0.8);
+ if (!p)
+ cairo_move_to (cr, x, y);
+ else
+ {
+ cairo_line_to (cr, x, y);
+
+ cairo_set_line_width (cr, 2);
+ cairo_stroke (cr);
+ }
+
+#if 0
+ cairo_rectangle (cr, floor (x - 0.5), floor (y - 0.5), 1, 1);
+ cairo_fill (cr);
+#endif
+
+ p = !p;
}
-int
-main (int argc, char **argv)
+static gboolean
+on_expose (GtkWidget *widget, GdkEvent *event, gpointer data)
{
+ if (!GTK_WIDGET_DRAWABLE (widget))
+ return TRUE;
+
seg_t pentagons[] = {
{ { df (10.2), df (2.2)}, { df (11.3), df (2.2) } },
{ { df (11.3), df (2.2) }, { df (15.7), df (5.5) } },
@@ -533,14 +606,135 @@ main (int argc, char **argv)
{ { df (15 + 10.2), df (2.2)}, { df (15 + 11.3), df (2.2) } },
{ { df (15 + 11.3), df (2.2) }, { df (15 + 15.7), df (5.5) } },
{ { df (15 + 15.7), df (5.5) }, { df (15 + 20.8), df (15.8) } },
- { { df (15 + 20.8), df (15.8) }, { df (15 + 13.2), df (25.2) } },
- { { df (15 + 13.2), df (25.2) }, { df (15 + 10.2), df (2.2) } }
+ { { df (15 + 20.8), df (15.8) }, { df (-5 + 13.2), df (25.2) } },
+ { { df (-5 + 13.2), df (25.2) }, { df (15 + 10.2), df (2.2) } },
+
+ { { df (7.0), df (2.0) }, { df (38.0), df (2.1) } },
+ { { df (7.0), df (12.0) }, { df (13.0), df (12.0) } },
+ { { df (7.0), df (2.0) }, { df (7.0), df (12.0) } },
+ { { df (13.0), df (12.0) }, { df (38.0), df (2.1) } },
};
+ cairo_t *cr = gdk_cairo_create (widget->window);
+ int i, j;
+
+ last_y = -1;
+ last_x = -1;
+ p = 0;
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+ for (i = 0; i < 40; ++i)
+ {
+ cairo_set_source_rgba (cr, 0.5, 0.5, 1, 0.8);
+
+ cairo_rectangle (cr, MULTIPLIER * i, 0, 1, MULTIPLIER * 50);
+ cairo_fill (cr);
+ }
+
+ for (i = 0; i < 30; ++i)
+ {
+ cairo_set_source_rgba (cr, 0.5, 0.5, 1, 0.8);
+
+ cairo_rectangle (cr, 0, MULTIPLIER * i, MULTIPLIER * 50, 1);
+ cairo_fill (cr);
+ }
+
polygon_t *polygon = polygon_create (
pentagons, sizeof (pentagons) / sizeof (pentagons[0]));
- polygon_rasterize (polygon, 0, 0, 45, 30, emit, NULL);
+ cairo_set_source_rgba (cr, 0.8, 0.2, 0.2, 1.0);
+ cairo_set_line_width (cr, 1);
+ for (i = 0; i < polygon->n_segments; ++i)
+ {
+ seg_t *seg = &(polygon->segments[i]);
+ double x0 = fixed_to_double (seg->p1.x);
+ double y0 = fixed_to_double (seg->p1.y);
+ double x1 = fixed_to_double (seg->p2.x);
+ double y1 = fixed_to_double (seg->p2.y);
+ cairo_move_to (cr, x0 * MULTIPLIER, y0 * MULTIPLIER);
+ cairo_line_to (cr, x1 * MULTIPLIER, y1 * MULTIPLIER);
+ cairo_stroke (cr);
+ }
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ polygon_rasterize (polygon, 0, 0, 45, 30, emit, cr);
+
+ cairo_set_source_rgba (cr, 1, 1, 1, 0.2);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ for (i = 0; i < 30; ++i)
+ {
+ int yy;
+ if ((i + 1) * MULTIPLIER < event->expose.area.y)
+ continue;
+ if (i * MULTIPLIER > event->expose.area.y + event->expose.area.height)
+ continue;
+ for (yy = 0; yy < N_GRID_Y; ++yy)
+ {
+ for (j = 0; j < 40; ++j)
+ {
+ int xx;
+
+ if ((j + 1) * MULTIPLIER < event->expose.area.x)
+ continue;
+ if (j * MULTIPLIER > event->expose.area.x + event->expose.area.width)
+ continue;
+
+ for (xx = 0; xx < N_GRID_X; ++xx)
+ {
+ double y =
+ (MULTIPLIER *
+ fixed_to_double (
+ sample_to_pos_y ((i << FIXED_BITS) | yy))) - 0.5;
+ double x =
+ (MULTIPLIER *
+ fixed_to_double (
+ sample_to_pos_x ((j << FIXED_BITS) | xx)) - 0.5);
+
+ cairo_rectangle (cr, x, y, 1, 1);
+
+ cairo_fill (cr);
+ }
+ }
+ }
+ }
+
+ return TRUE;
+
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window;
+ GtkWidget *area;
+ GtkWidget *sw;
+
+ gtk_init (&argc, &argv);
+
+ area = gtk_drawing_area_new ();
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_container_add (GTK_CONTAINER (window), sw);
+
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), area);
+
+ gtk_widget_set_size_request (area, MULTIPLIER * 50, MULTIPLIER * 50);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
+
+ gtk_widget_show_all (window);
+
+ g_signal_connect (area, "expose_event", G_CALLBACK (on_expose), NULL);
+ g_signal_connect (window, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
+
+
+ gtk_main ();
+
return 0;
}