gtk+ r22592 - in trunk: . demos/gtk-demo gdk
- From: behdad svn gnome org
- To: svn-commits-list gnome org
- Subject: gtk+ r22592 - in trunk: . demos/gtk-demo gdk
- Date: Fri, 27 Mar 2009 16:54:10 +0000 (UTC)
Author: behdad
Date: Fri Mar 27 16:54:10 2009
New Revision: 22592
URL: http://svn.gnome.org/viewvc/gtk+?rev=22592&view=rev
Log:
2009-03-27 Behdad Esfahbod <behdad gnome org>
Bug 437533 â Implement draw_shape PangoRenderer method
* gdk/gdkpango.c (gdk_pango_renderer_draw_shape),
(gdk_pango_renderer_class_init): Implement draw_shape
* demos/gtk-demo/rotated_text.c (fancy_shape_renderer),
(create_fancy_attr_list_for_layout), (rotated_text_expose_event),
(do_rotated_text):
1) Port to pangocairo
2) Also show a rotated label
3) Install a custom shape renderer on both. The second one goes
through gdkpango and hence tests the patch above. It's working.
Modified:
trunk/ChangeLog
trunk/demos/gtk-demo/rotated_text.c
trunk/gdk/gdkpango.c
Modified: trunk/demos/gtk-demo/rotated_text.c
==============================================================================
--- trunk/demos/gtk-demo/rotated_text.c (original)
+++ trunk/demos/gtk-demo/rotated_text.c Fri Mar 27 16:54:10 2009
@@ -1,101 +1,173 @@
/* 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.
+ * This demo shows how to use PangoCairo to draw rotated and transformed
+ * text. The right pane shows a rotated GtkLabel widget.
*
- * 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.
+ * In both cases, a custom PangoCairo shape renderer is installed to draw
+ * a red heard using cairo drawing operations instead of the Unicode heart
+ * character.
*/
-#include <math.h>
+
#include <gtk/gtk.h>
+#include <string.h>
static GtkWidget *window = NULL;
+#define HEART "â"
+const char text[] = "I â GTK+";
+
+static void
+fancy_shape_renderer (cairo_t *cr,
+ PangoAttrShape *attr,
+ gboolean do_path,
+ gpointer data)
+{
+ double x, y;
+ cairo_get_current_point (cr, &x, &y);
+ cairo_translate (cr, x, y);
+
+ cairo_scale (cr,
+ (double) attr->ink_rect.width / PANGO_SCALE,
+ (double) attr->ink_rect.height / PANGO_SCALE);
+
+ switch (GPOINTER_TO_UINT (attr->data))
+ {
+ case 0x2665: /* U+2665 BLACK HEART SUIT */
+ {
+ cairo_move_to (cr, .5, .0);
+ cairo_line_to (cr, .9, -.4);
+ cairo_curve_to (cr, 1.1, -.8, .5, -.9, .5, -.5);
+ cairo_curve_to (cr, .5, -.9, -.1, -.8, .1, -.4);
+ cairo_close_path (cr);
+ }
+ break;
+ }
+
+ if (!do_path) {
+ cairo_set_source_rgb (cr, 1., 0., 0.);
+ cairo_fill (cr);
+ }
+}
+
+PangoAttrList *
+create_fancy_attr_list_for_layout (PangoLayout *layout)
+{
+ PangoAttrList *attrs;
+ PangoFontMetrics *metrics;
+ int ascent;
+ PangoRectangle ink_rect, logical_rect;
+ const char *p;
+
+ /* Get font metrics and prepare fancy shape size */
+ metrics = pango_context_get_metrics (pango_layout_get_context (layout),
+ pango_layout_get_font_description (layout),
+ NULL);
+ ascent = pango_font_metrics_get_ascent (metrics);
+ logical_rect.x = 0;
+ logical_rect.width = ascent;
+ logical_rect.y = -ascent;
+ logical_rect.height = ascent;
+ ink_rect = logical_rect;
+ pango_font_metrics_unref (metrics);
+
+ /* Set fancy shape attributes for all hearts */
+ attrs = pango_attr_list_new ();
+ for (p = text; (p = strstr (p, HEART)); p += strlen (HEART))
+ {
+ PangoAttribute *attr;
+
+ attr = pango_attr_shape_new_with_data (&ink_rect,
+ &logical_rect,
+ GUINT_TO_POINTER (g_utf8_get_char (p)),
+ NULL, NULL);
+
+ attr->start_index = p - text;
+ attr->end_index = attr->start_index + strlen (HEART);
+
+ pango_attr_list_insert (attrs, attr);
+ }
+
+ return attrs;
+}
+
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;
+#define N_WORDS 5
+#define FONT "Serif 18"
+
PangoContext *context;
PangoLayout *layout;
PangoFontDescription *desc;
+ cairo_t *cr;
+ cairo_pattern_t *pattern;
+
+ PangoAttrList *attrs;
+
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 */
+ /* Create a cairo context and 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. */
+ cr = gdk_cairo_create (widget->window);
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);
+ cairo_translate (cr,
+ device_radius + (width - 2 * device_radius) / 2,
+ device_radius + (height - 2 * device_radius) / 2);
+ cairo_scale (cr, device_radius / RADIUS, device_radius / RADIUS);
+
+ /* Create and a subtle gradient source and use it. */
+ pattern = cairo_pattern_create_linear (-RADIUS, -RADIUS, RADIUS, RADIUS);
+ cairo_pattern_add_color_stop_rgb (pattern, 0., .5, .0, .0);
+ cairo_pattern_add_color_stop_rgb (pattern, 1., .0, .0, .5);
+ cairo_set_source (cr, pattern);
- /* Create a PangoLayout, set the font and text */
+ /* Create a PangoContext and set up our shape renderer */
context = gtk_widget_create_pango_context (widget);
+ pango_cairo_context_set_shape_renderer (context,
+ fancy_shape_renderer,
+ NULL, NULL);
+
+ /* Create a PangoLayout, set the text, font, and attributes */
layout = pango_layout_new (context);
- pango_layout_set_text (layout, "Text", -1);
+ 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);
+
+ attrs = create_fancy_attr_list_for_layout (layout);
+ pango_layout_set_attributes (layout, attrs);
+ pango_attr_list_unref (attrs);
/* 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) * G_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_cairo_update_layout (cr, layout);
- pango_layout_get_size (layout, &width, &height);
- pango_renderer_draw_layout (renderer, layout,
- - width / 2, - RADIUS * PANGO_SCALE);
- }
+ pango_layout_get_pixel_size (layout, &width, &height);
+ cairo_move_to (cr, - width / 2, - RADIUS * .9);
+ pango_cairo_show_layout (cr, layout);
- /* 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);
+ /* Rotate for the next turn */
+ cairo_rotate (cr, G_PI*2 / N_WORDS);
+ }
/* free the objects we created */
+ pango_font_description_free (desc);
g_object_unref (layout);
g_object_unref (context);
+ cairo_pattern_destroy (pattern);
+ cairo_destroy (cr);
return FALSE;
}
@@ -103,21 +175,30 @@
GtkWidget *
do_rotated_text (GtkWidget *do_widget)
{
- GtkWidget *drawing_area;
-
if (!window)
{
+ GtkWidget *box;
+ GtkWidget *drawing_area;
+ GtkWidget *label;
+ PangoLayout *layout;
+ PangoAttrList *attrs;
+
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");
-
+ gtk_window_set_default_size (GTK_WINDOW (window), 4 * RADIUS, 2 * RADIUS);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);
+ box = gtk_hbox_new (TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (window), box);
+
+ /* Add a drawing area */
+
drawing_area = gtk_drawing_area_new ();
- gtk_container_add (GTK_CONTAINER (window), drawing_area);
+ gtk_container_add (GTK_CONTAINER (box), drawing_area);
/* This overrides the background color from the theme */
gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &white);
@@ -125,7 +206,21 @@
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);
+ /* And a label */
+
+ label = gtk_label_new (text);
+ gtk_container_add (GTK_CONTAINER (box), label);
+
+ gtk_label_set_angle (label, 45);
+
+ /* Set up fancy stuff on the label */
+ layout = gtk_label_get_layout (label);
+ pango_cairo_context_set_shape_renderer (pango_layout_get_context (layout),
+ fancy_shape_renderer,
+ NULL, NULL);
+ attrs = create_fancy_attr_list_for_layout (layout);
+ gtk_label_set_attributes (label, attrs);
+ pango_attr_list_unref (attrs);
}
if (!GTK_WIDGET_VISIBLE (window))
Modified: trunk/gdk/gdkpango.c
==============================================================================
--- trunk/gdk/gdkpango.c (original)
+++ trunk/gdk/gdkpango.c Fri Mar 27 16:54:10 2009
@@ -312,6 +312,52 @@
}
static void
+gdk_pango_renderer_draw_shape (PangoRenderer *renderer,
+ PangoAttrShape *attr,
+ int x,
+ int y)
+{
+ GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
+ GdkPangoRendererPrivate *priv = gdk_renderer->priv;
+ PangoLayout *layout;
+ PangoCairoShapeRendererFunc shape_renderer;
+ gpointer shape_renderer_data;
+ cairo_t *cr;
+ double dx = (double)x / PANGO_SCALE, dy = (double)y / PANGO_SCALE;
+
+ layout = pango_renderer_get_layout (renderer);
+
+ if (!layout)
+ return;
+
+ shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (layout),
+ &shape_renderer_data);
+
+ if (!shape_renderer)
+ return;
+
+ cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_FOREGROUND);
+
+ cairo_save (cr);
+
+ if (priv->embossed)
+ {
+ cairo_save (cr);
+ emboss_context (gdk_renderer, cr);
+
+ cairo_move_to (cr, dx, dy);
+ shape_renderer (cr, attr, FALSE, shape_renderer_data);
+
+ cairo_restore (cr);
+ }
+
+ cairo_move_to (cr, dx, dy);
+ shape_renderer (cr, attr, FALSE, shape_renderer_data);
+
+ cairo_restore (cr);
+}
+
+static void
gdk_pango_renderer_part_changed (PangoRenderer *renderer,
PangoRenderPart part)
{
@@ -474,6 +520,7 @@
renderer_class->draw_glyphs = gdk_pango_renderer_draw_glyphs;
renderer_class->draw_rectangle = gdk_pango_renderer_draw_rectangle;
renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline;
+ renderer_class->draw_shape = gdk_pango_renderer_draw_shape;
renderer_class->part_changed = gdk_pango_renderer_part_changed;
renderer_class->begin = gdk_pango_renderer_begin;
renderer_class->end = gdk_pango_renderer_end;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]