diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-12-21 15:59:21 -0500 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-12-21 16:29:28 -0500 |
commit | 0a7705cb5bb4525336a7b0f3d32b4fa3bbda4228 (patch) | |
tree | c3a15400a44f66f242179fa460fe79e5fe56f04f | |
parent | bb03de6de3d616ea8f6812fcf664d987f29263e8 (diff) |
-rw-r--r-- | poly3.c | 228 |
1 files changed, 211 insertions, 17 deletions
@@ -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; } |