diff options
Diffstat (limited to 'demos/gtk-demo/rotated_text.c')
-rw-r--r-- | demos/gtk-demo/rotated_text.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/demos/gtk-demo/rotated_text.c b/demos/gtk-demo/rotated_text.c new file mode 100644 index 000000000..1c37548dd --- /dev/null +++ b/demos/gtk-demo/rotated_text.c @@ -0,0 +1,142 @@ +/* Rotated Text + * + * This demo shows how to use GDK and Pango to draw rotated and transformed + * text. The use of GdkPangoRenderer in this example is a somewhat advanced + * technique; most applications can simply use gdk_draw_layout(). We use + * it here mostly because that allows us to work in user coordinates - that is, + * coordinates prior to the application of the transformation matrix, rather + * than device coordinates. + * + * As of GTK+-2.6, the ability to draw transformed and anti-aliased graphics + * as shown in this example is only present for text. With GTK+-2.8, a new + * graphics system called "Cairo" will be introduced that provides these + * capabilities and many more for all types of graphics. + */ +#include <math.h> +#include <gtk/gtk.h> + +static GtkWidget *window = NULL; + +static gboolean +rotated_text_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer data) +{ +#define RADIUS 150 +#define N_WORDS 10 +#define FONT "Sans Bold 27" + + PangoRenderer *renderer; + PangoMatrix matrix = PANGO_MATRIX_INIT; + PangoContext *context; + PangoLayout *layout; + PangoFontDescription *desc; + + int width = widget->allocation.width; + int height = widget->allocation.height; + double device_radius; + int i; + + /* Get the default renderer for the screen, and set it up for drawing */ + renderer = gdk_pango_renderer_get_default (gtk_widget_get_screen (widget)); + gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), widget->window); + gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), widget->style->black_gc); + + /* Set up a transformation matrix so that the user space coordinates for + * the centered square where we draw are [-RADIUS, RADIUS], [-RADIUS, RADIUS] + * We first center, then change the scale */ + device_radius = MIN (width, height) / 2.; + pango_matrix_translate (&matrix, + device_radius + (width - 2 * device_radius) / 2, + device_radius + (height - 2 * device_radius) / 2); + pango_matrix_scale (&matrix, device_radius / RADIUS, device_radius / RADIUS); + + /* Create a PangoLayout, set the font and text */ + context = gtk_widget_create_pango_context (widget); + layout = pango_layout_new (context); + pango_layout_set_text (layout, "Text", -1); + desc = pango_font_description_from_string (FONT); + pango_layout_set_font_description (layout, desc); + pango_font_description_free (desc); + + /* Draw the layout N_WORDS times in a circle */ + for (i = 0; i < N_WORDS; i++) + { + GdkColor color; + PangoMatrix rotated_matrix = matrix; + int width, height; + double angle = (360. * i) / N_WORDS; + + /* Gradient from red at angle == 60 to blue at angle == 300 */ + color.red = 65535 * (1 + cos ((angle - 60) * M_PI / 180.)) / 2; + color.green = 0; + color.blue = 65535 - color.red; + + gdk_pango_renderer_set_override_color (GDK_PANGO_RENDERER (renderer), + PANGO_RENDER_PART_FOREGROUND, &color); + + pango_matrix_rotate (&rotated_matrix, angle); + + pango_context_set_matrix (context, &rotated_matrix); + + /* Inform Pango to re-layout the text with the new transformation matrix */ + pango_layout_context_changed (layout); + + pango_layout_get_size (layout, &width, &height); + pango_renderer_draw_layout (renderer, layout, + - width / 2, - RADIUS * PANGO_SCALE); + } + + /* Clean up default renderer, since it is shared */ + gdk_pango_renderer_set_override_color (GDK_PANGO_RENDERER (renderer), + PANGO_RENDER_PART_FOREGROUND, NULL); + gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), NULL); + gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), NULL); + + /* free the objects we created */ + g_object_unref (layout); + g_object_unref (context); + + return FALSE; +} + +GtkWidget * +do_rotated_text (GtkWidget *do_widget) +{ + GtkWidget *drawing_area; + + if (!window) + { + const GdkColor white = { 0, 0xffff, 0xffff, 0xffff }; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_screen (GTK_WINDOW (window), + gtk_widget_get_screen (do_widget)); + gtk_window_set_title (GTK_WINDOW (window), "Rotated Text"); + + g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window); + + drawing_area = gtk_drawing_area_new (); + gtk_container_add (GTK_CONTAINER (window), drawing_area); + + /* This overrides the background color from the theme */ + gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &white); + + g_signal_connect (drawing_area, "expose-event", + G_CALLBACK (rotated_text_expose_event), NULL); + + gtk_window_set_default_size (GTK_WINDOW (window), 2 * RADIUS, 2 * RADIUS); + } + + if (!GTK_WIDGET_VISIBLE (window)) + { + gtk_widget_show_all (window); + } + else + { + gtk_widget_destroy (window); + window = NULL; + } + + return window; +} |