diff --git a/demos/gtk-demo/fontrendering.c b/demos/gtk-demo/fontrendering.c index e95a78f7e7..97eff2f597 100644 --- a/demos/gtk-demo/fontrendering.c +++ b/demos/gtk-demo/fontrendering.c @@ -1,6 +1,11 @@ /* Pango/Font Rendering * - * Demonstrates various aspects of font rendering. + * Demonstrates various aspects of font rendering, + * such as hinting, antialiasing and grid alignment. + * + * The demo lets you explore font rendering options + * interactively to get a feeling for they affect the + * shape and positioning of the glyphs. */ #include @@ -17,10 +22,14 @@ static GtkWidget *down_button = NULL; static GtkWidget *text_radio = NULL; static GtkWidget *show_grid = NULL; static GtkWidget *show_extents = NULL; +static GtkWidget *show_pixels = NULL; +static GtkWidget *show_outlines = NULL; static PangoContext *context; -static int scale = 9; +static int scale = 7; +static double pixel_alpha = 1.0; +static double outline_alpha = 0.0; static void update_image (void) @@ -39,6 +48,7 @@ update_image (void) cairo_hint_style_t hintstyle; cairo_hint_metrics_t hintmetrics; cairo_antialias_t antialias; + cairo_path_t *path; if (!context) context = gtk_widget_create_pango_context (image); @@ -94,10 +104,14 @@ update_image (void) cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint (cr); - cairo_set_source_rgb (cr, 0, 0, 0); + cairo_set_source_rgba (cr, 0, 0, 0, pixel_alpha); + cairo_move_to (cr, 10, 10); pango_cairo_show_layout (cr, layout); + pango_cairo_layout_path (cr, layout); + path = cairo_copy_path (cr); + cairo_destroy (cr); g_object_unref (layout); @@ -136,7 +150,7 @@ update_image (void) if (gtk_check_button_get_active (GTK_CHECK_BUTTON (show_extents))) { - cairo_set_source_rgba (cr, 0, 0, 1, 1); + cairo_set_source_rgb (cr, 0, 0, 1); cairo_rectangle (cr, scale * (10 + pango_units_to_double (logical.x)) - 0.5, @@ -149,7 +163,7 @@ update_image (void) cairo_line_to (cr, scale * (10 + pango_units_to_double (logical.x + logical.width)) + 1, scale * (10 + pango_units_to_double (baseline)) - 0.5); cairo_stroke (cr); - cairo_set_source_rgba (cr, 1, 0, 0, 1); + cairo_set_source_rgb (cr, 1, 0, 0); cairo_rectangle (cr, scale * (10 + pango_units_to_double (pink.x)) + 0.5, scale * (10 + pango_units_to_double (pink.y)) + 0.5, @@ -158,8 +172,36 @@ update_image (void) cairo_stroke (cr); } + for (int i = 0; i < path->num_data; i += path->data[i].header.length) + { + cairo_path_data_t *data = &path->data[i]; + switch (data->header.type) + { + case CAIRO_PATH_CURVE_TO: + data[3].point.x *= scale; data[3].point.y *= scale; + data[2].point.x *= scale; data[2].point.y *= scale; + data[1].point.x *= scale; data[1].point.y *= scale; + break; + case CAIRO_PATH_LINE_TO: + case CAIRO_PATH_MOVE_TO: + data[1].point.x *= scale; data[1].point.y *= scale; + break; + case CAIRO_PATH_CLOSE_PATH: + break; + default: + g_assert_not_reached (); + } + } + + cairo_set_source_rgba (cr, 0, 0, 1, outline_alpha); + cairo_move_to (cr, scale * 20 - 0.5, scale * 20 - 0.5); + cairo_append_path (cr, path); + cairo_stroke (cr); + cairo_surface_destroy (surface); cairo_destroy (cr); + + cairo_path_destroy (path); } else { @@ -167,10 +209,26 @@ update_image (void) PangoLayoutRun *run; PangoGlyphInfo *g; int i, j; + GString *str; + gunichar ch; + + if (*text == '\0') + text = " "; + + ch = g_utf8_get_char (text); + + str = g_string_new (""); + + for (i = 0; i < 4; i++) + { + g_string_append_unichar (str, ch); + g_string_append_unichar (str, 0x200c); + } layout = pango_layout_new (context); pango_layout_set_font_description (layout, desc); - pango_layout_set_text (layout, "aaaa", -1); + pango_layout_set_text (layout, str->str, -1); + g_string_free (str, TRUE); pango_layout_get_extents (layout, &ink, &logical); pango_extents_to_pixels (&logical, NULL); @@ -185,7 +243,7 @@ update_image (void) cairo_set_source_rgb (cr, 0, 0, 0); for (i = 0; i < 4; i++) { - g = &(run->glyphs->glyphs[i]); + g = &(run->glyphs->glyphs[2*i]); g->geometry.width = PANGO_UNITS_ROUND (g->geometry.width * 3 / 2); } @@ -193,7 +251,7 @@ update_image (void) { for (i = 0; i < 4; i++) { - g = &(run->glyphs->glyphs[i]); + g = &(run->glyphs->glyphs[2*i]); g->geometry.x_offset = i * (PANGO_SCALE / 4); g->geometry.y_offset = j * (PANGO_SCALE / 4); } @@ -212,7 +270,6 @@ update_image (void) cairo_surface_destroy (surface); } - gtk_picture_set_pixbuf (GTK_PICTURE (image), pixbuf2); g_object_unref (pixbuf2); @@ -220,6 +277,78 @@ update_image (void) pango_font_description_free (desc); } +static gboolean fading = FALSE; +static double start_pixel_alpha; +static double end_pixel_alpha; +static double start_outline_alpha; +static double end_outline_alpha; +static gint64 start_time; +static gint64 end_time; + +static double +ease_out_cubic (double t) +{ + double p = t - 1; + return p * p * p + 1; +} + +static gboolean +change_alpha (GtkWidget *widget, + GdkFrameClock *clock, + gpointer user_data) +{ + gint64 now = g_get_monotonic_time (); + double t; + + t = ease_out_cubic ((now - start_time) / (double) (end_time - start_time)); + + pixel_alpha = start_pixel_alpha + (end_pixel_alpha - start_pixel_alpha) * t; + outline_alpha = start_outline_alpha + (end_outline_alpha - start_outline_alpha) * t; + + update_image (); + + if (now >= end_time) + { + fading = FALSE; + return G_SOURCE_REMOVE; + } + + return G_SOURCE_CONTINUE; +} + +static void +start_alpha_fade (void) +{ + gboolean pixels; + gboolean outlines; + + if (fading) + return; + + pixels = gtk_check_button_get_active (GTK_CHECK_BUTTON (show_pixels)); + outlines = gtk_check_button_get_active (GTK_CHECK_BUTTON (show_outlines)); + + start_pixel_alpha = pixel_alpha; + if (pixels && outlines) + end_pixel_alpha = 0.5; + else if (pixels) + end_pixel_alpha = 1; + else + end_pixel_alpha = 0; + + start_outline_alpha = outline_alpha; + if (outlines) + end_outline_alpha = 1.0; + else + end_outline_alpha = 0.0; + + start_time = g_get_monotonic_time (); + end_time = start_time + G_TIME_SPAN_SECOND / 2; + + fading = TRUE; + gtk_widget_add_tick_callback (window, change_alpha, NULL, NULL); +} + static void update_buttons (void) { @@ -227,20 +356,26 @@ update_buttons (void) gtk_widget_set_sensitive (down_button, scale > 1); } -static void -scale_up (void) +static gboolean +scale_up (GtkWidget *widget, + GVariant *args, + gpointer user_data) { scale += 1; update_buttons (); update_image (); + return TRUE; } -static void -scale_down (void) +static gboolean +scale_down (GtkWidget *widget, + GVariant *args, + gpointer user_data) { scale -= 1; update_buttons (); update_image (); + return TRUE; } GtkWidget * @@ -266,6 +401,8 @@ do_fontrendering (GtkWidget *do_widget) text_radio = GTK_WIDGET (gtk_builder_get_object (builder, "text_radio")); show_grid = GTK_WIDGET (gtk_builder_get_object (builder, "show_grid")); show_extents = GTK_WIDGET (gtk_builder_get_object (builder, "show_extents")); + show_pixels = GTK_WIDGET (gtk_builder_get_object (builder, "show_pixels")); + show_outlines = GTK_WIDGET (gtk_builder_get_object (builder, "show_outlines")); g_signal_connect (up_button, "clicked", G_CALLBACK (scale_up), NULL); g_signal_connect (down_button, "clicked", G_CALLBACK (scale_down), NULL); @@ -277,6 +414,8 @@ do_fontrendering (GtkWidget *do_widget) g_signal_connect (text_radio, "notify::active", G_CALLBACK (update_image), NULL); g_signal_connect (show_grid, "notify::active", G_CALLBACK (update_image), NULL); g_signal_connect (show_extents, "notify::active", G_CALLBACK (update_image), NULL); + g_signal_connect (show_pixels, "notify::active", G_CALLBACK (start_alpha_fade), NULL); + g_signal_connect (show_outlines, "notify::active", G_CALLBACK (start_alpha_fade), NULL); update_image (); diff --git a/demos/gtk-demo/fontrendering.ui b/demos/gtk-demo/fontrendering.ui index fc7a9fed4a..44b65c9a19 100644 --- a/demos/gtk-demo/fontrendering.ui +++ b/demos/gtk-demo/fontrendering.ui @@ -1,13 +1,8 @@ - - 24 - 1 - 4 - - 1080 - 430 + 1024 + 768 @@ -87,20 +82,20 @@ - - Hinting - 1 - + + Show _Pixels + 1 + 1 3 + 0 - - Antialias + + Show _Outline + 1 3 1 @@ -108,45 +103,73 @@ - - 0 - center - - None - Slight - Medium - Full - + + 6 + + + _Hinting + 1 + hinting + + + + + + 0 + center + + None + Slight + Medium + Full + + + 4 + 2 + + + + + + _Antialias + 1 + 1 + + 4 + 1 - Hint Metrics + Hint _Metrics + 1 - 4 + 5 1 - Show Extents - 1 + Show _Extents + 1 - 5 + 6 0 - 1 - Show Grid + Show _Grid + 1 - 5 + 6 1 @@ -157,8 +180,19 @@ + + + managed + + + <Control>plus + activate + + + + - 6 + 7 0 @@ -169,8 +203,19 @@ + + + managed + + + <Control>minus + activate + + + + - 6 + 7 1 @@ -179,7 +224,7 @@ 1 - 7 + 8