diff --git a/deck.c b/deck.c index 74df0fc..8403489 100644 --- a/deck.c +++ b/deck.c @@ -1,8 +1,10 @@ #include "deck.h" +#include #define MARGIN 18 #define RATIO 1.414 -#define N_SLIDES 30 +#define N_SLIDES 5 +#define MASK_SIZE 24 struct Deck { @@ -11,6 +13,9 @@ struct Deck int view_width; int thumb_width; + + cairo_pattern_t * top_mask; + cairo_pattern_t * bottom_mask; }; Deck * @@ -29,6 +34,18 @@ void deck_set_main_width (Deck *deck, int view_width) { deck->view_width = view_width; + + if (deck->top_mask) + { + cairo_pattern_destroy (deck->top_mask); + deck->top_mask = NULL; + } + + if (deck->bottom_mask) + { + cairo_pattern_destroy (deck->bottom_mask); + deck->bottom_mask = NULL; + } } static int @@ -50,6 +67,141 @@ deck_get_thumb_slide_height (Deck *deck) } static void +make_gamma_correct_gradient (cairo_pattern_t *gradient, + double from, double to, + int n_blocks) +{ + if (n_blocks == 1) + { + cairo_pattern_add_color_stop_rgba (gradient, from, 1.0, 1.0, 1.0, + (1 - pow(from , 1/2.2))); + cairo_pattern_add_color_stop_rgba (gradient, to, 1.0, 1.0, 1.0, + (1 - pow(from, 1/2.2))); + } + else + { + make_gamma_correct_gradient (gradient, from, to / 2, n_blocks / 2); + make_gamma_correct_gradient (gradient, to / 2, to, n_blocks / 2); + } +} + + +static cairo_pattern_t * +create_gradient_mask (cairo_t *cr, gboolean top) +{ + cairo_pattern_t *gradient; + double begin = top? 0.0 : 1.0; + double end = top? 1.0 : 0.0; + double mid = top? 0.8 : 0.8; + double i; + + cairo_push_group_with_content (cr, CAIRO_CONTENT_ALPHA); + + cairo_save (cr); + + gradient = cairo_pattern_create_linear (0.0, 0.0, 0.0, MASK_SIZE); + + cairo_pattern_add_color_stop_rgba (gradient, 0.0, 1.0, 1.0, 1.0, begin); + cairo_pattern_add_color_stop_rgba (gradient, 0.5, 1.0, 1.0, 1.0, mid); + cairo_pattern_add_color_stop_rgba (gradient, 1.0, 1.0, 1.0, 1.0, end); + + cairo_set_source (cr, gradient); + + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + + cairo_paint (cr); + + cairo_pattern_destroy (gradient); + + cairo_restore (cr); + + return cairo_pop_group (cr); +} + +static void +ensure_masks (Deck *deck, + cairo_t *cr, + int width) +{ + double dev_x, dev_y; + cairo_matrix_t matrix; + + cairo_save (cr); + + /* Limit the size of the mask surfaces */ + cairo_rectangle (cr, 0, 0, width, MASK_SIZE); + cairo_clip (cr); + + if (!deck->top_mask) + { + deck->top_mask = create_gradient_mask (cr, TRUE); +#if 0 + cairo_pattern_set_matrix (deck->top_mask, &matrix); +#endif + } + + if (!deck->bottom_mask) + { + deck->bottom_mask = create_gradient_mask (cr, FALSE); +#if 0 + cairo_pattern_set_matrix (deck->bottom_mask, &matrix); +#endif + } + + cairo_restore (cr); +} + +static void +layout_set_font (PangoLayout *layout, const char *font) +{ + PangoFontDescription *desc = pango_font_description_from_string (font); + + pango_layout_set_font_description (layout, desc); + + pango_font_description_free (desc); +} + +FooScrollArea *the_area; + +static void +draw_text (cairo_t *cr, + int width, + int x, + int y) +{ + PangoLayout *layout; + PangoRectangle logical, ink; + char *string = + "A spectre is haunting Europe \342\200\223 the spectre of communism. All the " + "powers of old Europe have entered into a holy alliance to exorcise " + "this spectre: Pope and Tsar, Metternich and Guizot, French Radicals " + "and German police-spies."; + + cairo_save (cr); + + layout = gtk_widget_create_pango_layout (GTK_WIDGET (the_area), string); + + layout_set_font (layout, "Century Old Style 28"); + + pango_layout_set_width (layout, PANGO_SCALE * width); + + pango_layout_get_pixel_extents (layout, &ink, &logical); + + x += logical.x; + y += logical.y; + + cairo_move_to (cr, x, y); + + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); + + pango_cairo_show_layout (cr, layout); + + cairo_restore (cr); + + g_object_unref (layout); +} + +static void deck_paint (Deck *deck, cairo_t *cr, int orig_x, @@ -59,7 +211,7 @@ deck_paint (Deck *deck, { int height; int i; - + height = get_slide_height (width); width -= 2 * MARGIN; @@ -81,9 +233,16 @@ deck_paint (Deck *deck, cairo_set_line_width (cr, 2); cairo_stroke (cr); + if (!is_thumbnail) + { + draw_text (cr, deck->view_width - 10 * MARGIN, + x + 2 * MARGIN, y + 2 * MARGIN); + } + cairo_set_source_rgba (cr, (i + 1.0) / N_SLIDES, 0, 1 - (i + 1.0) / N_SLIDES, 1); +#if 0 if (is_thumbnail) { cairo_rectangle (cr, x + width/2 - 4, y + height/2 - 4, @@ -96,16 +255,96 @@ deck_paint (Deck *deck, } cairo_fill (cr); +#endif } } +static void +translate_pattern (cairo_pattern_t *pattern, + double dx, double dy) +{ + cairo_matrix_t matrix; + + cairo_pattern_get_matrix (pattern, &matrix); + cairo_matrix_translate (&matrix, dx, dy); + cairo_pattern_set_matrix (pattern, &matrix); +} + void deck_paint_main (Deck *deck, cairo_t *cr, int orig_x, - int orig_y) + int orig_y, + GdkRectangle *viewport) { + cairo_pattern_t *mask; + + cairo_save (cr); + + cairo_rectangle (cr, + viewport->x, viewport->y + MASK_SIZE, + viewport->width, viewport->height - 2 * MASK_SIZE); + cairo_clip (cr); + + deck_paint (deck, cr, orig_x, orig_y, deck->view_width, FALSE); + + cairo_restore (cr); + + /* top mask */ + cairo_save (cr); + + + cairo_rectangle (cr, viewport->x, viewport->y, + viewport->width, MASK_SIZE); + cairo_clip (cr); + +#if 0 + cairo_rectangle (cr, + viewport->x + MARGIN, viewport->y, + viewport->width - 2 * MARGIN, + MASK_SIZE); + + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_fill (cr); +#endif + + cairo_push_group (cr); + deck_paint (deck, cr, orig_x, orig_y, deck->view_width, FALSE); + cairo_pop_group_to_source(cr); + + cairo_translate (cr, viewport->x, viewport->y); + mask = create_gradient_mask (cr, TRUE); + cairo_mask (cr, mask); + cairo_pattern_destroy (mask); + + cairo_restore (cr); + + + /* bottom mask */ + cairo_save (cr); + + cairo_rectangle (cr, + viewport->x, viewport->y + viewport->height - MASK_SIZE, + viewport->width, MASK_SIZE); + cairo_clip (cr); + + + cairo_push_group (cr); + deck_paint (deck, cr, orig_x, orig_y, deck->view_width, FALSE); + + cairo_pop_group_to_source(cr); + + cairo_translate (cr, + viewport->x, + viewport->y + viewport->height - MASK_SIZE); + + mask = create_gradient_mask (cr, FALSE); + + cairo_mask (cr, mask); + cairo_pattern_destroy (mask); + + cairo_restore (cr); } void diff --git a/deck.h b/deck.h index 3ba2357..b27b550 100644 --- a/deck.h +++ b/deck.h @@ -10,7 +10,8 @@ Deck *deck_new (DeckChangeNotify notify, void deck_paint_main (Deck *deck, cairo_t *cr, int x, - int y); + int y, + GdkRectangle *viewport); void deck_paint_thumbs (Deck *deck, cairo_t *cr, int x, diff --git a/main.c b/main.c index 0230d69..5534500 100644 --- a/main.c +++ b/main.c @@ -124,7 +124,10 @@ on_main_paint (FooScrollArea *scroll_area, cairo_save (cr); - deck_paint_main (app->deck, cr, get_toolbar_width (app), 0); + viewport.x += get_toolbar_width (app); + viewport.width -= get_toolbar_width (app); + + deck_paint_main (app->deck, cr, get_toolbar_width (app), 0, &viewport); cairo_restore (cr); paint_toolbar (app, scroll_area, cr); @@ -221,6 +224,8 @@ on_viewport_changed (FooScrollArea *scroll_area, /* Invalidate toolbar */ invalidate_toolbar (app, old_viewport); invalidate_toolbar (app, viewport); + + foo_scroll_area_invalidate (scroll_area); } static void @@ -277,7 +282,7 @@ main (int argc, char **argv) app->deck = deck_new (on_deck_changed, app); app->toolbar = toolbar_new (); - + gtk_container_add ( GTK_CONTAINER (get_widget (app, "main_area_scrolled_window")), GTK_WIDGET (app->main_area)); @@ -288,6 +293,10 @@ main (int argc, char **argv) foo_scroll_area_set_min_size (app->thumbnails, 200, -1); + extern FooScrollArea *the_area; + + the_area = app->main_area; + g_signal_connect (app->main_area, "paint", G_CALLBACK (on_main_paint), app); g_signal_connect (app->main_area, "viewport_size_changed", diff --git a/toolbar.c b/toolbar.c index 23897b1..4802535 100644 --- a/toolbar.c +++ b/toolbar.c @@ -46,16 +46,6 @@ toolbar_get_width (Toolbar *bar) } static void -layout_set_font (PangoLayout *layout, const char *font) -{ - PangoFontDescription *desc = pango_font_description_from_string (font); - - pango_layout_set_font_description (layout, desc); - - pango_font_description_free (desc); -} - -static void on_input (FooScrollArea *area, FooScrollAreaEvent *event, gpointer data) @@ -77,6 +67,16 @@ on_input (FooScrollArea *area, } static void +layout_set_font (PangoLayout *layout, const char *font) +{ + PangoFontDescription *desc = pango_font_description_from_string (font); + + pango_layout_set_font_description (layout, desc); + + pango_font_description_free (desc); +} + +static void draw_number (FooScrollArea *area, cairo_t *cr, int number,