static gboolean text_item_renderer (AboutRenderer *r, AboutState *state) { PangoLayout *layout = r->layout; int age = state->now - r->start_time; double rage = CLAMP (age / (double)r->duration, 0.0, 1.0); GtkWidget *widget = state->anim_area; GtkStyleContext *ctxt; const int fade = 500; int x, y, width, height; cairo_t *cr; GtkAllocation wa; GdkRGBA color; double alpha = 1; if (age >= r->duration) return FALSE; if (r->fade_in && age < fade) alpha = age / (double)fade; else if (r->fade_out && r->duration - age < fade) alpha = (r->duration - age) / (double)fade; ctxt = gtk_widget_get_style_context (widget); gtk_widget_get_allocation (widget, &wa); x = (int)(PANGO_SCALE * wa.width * (r->start.x + rage * (r->end.x - r->start.x))); y = (int)(PANGO_SCALE * wa.height * (r->start.y + rage * (r->end.y - r->start.y))); if (r->expansion.count) { PangoAttrList *attrlist = pango_layout_get_attributes (layout); const char *p, *text = pango_layout_get_text (layout); PangoRectangle ink, logical; memset (&ink, 0, sizeof (ink)); logical = ink; logical.width = (int)(rage * r->expansion.rate * r->natural_width / r->expansion.count); p = text; while (*p) { const char *next = g_utf8_next_char (p); gunichar uc = g_utf8_get_char (p); PangoAttribute *attr; if (uc == UNICODE_ZERO_WIDTH_SPACE_C) { attr = pango_attr_shape_new (&ink, &logical); attr->start_index = p - text; attr->end_index = next - text; pango_attr_list_change (attrlist, attr); } p = next; } pango_layout_set_attributes (layout, attrlist); } pango_layout_get_size (layout, &width, &height); x -= width / 2; y -= height / 2; cr = r->cr; gnm_style_context_get_color (ctxt, GTK_STATE_FLAG_NORMAL, &color); color.alpha = alpha; gdk_cairo_set_source_rgba (cr, &color); cairo_move_to (cr, x / (double)PANGO_SCALE, y / (double)PANGO_SCALE); pango_cairo_show_layout (cr, layout); return TRUE; }
static void decorate_text (GimpAboutDialog *dialog, gint anim_type, gdouble time) { GtkStyle *style = gtk_widget_get_style (dialog->anim_area); const gchar *text; const gchar *ptr; gint letter_count = 0; gint text_length = 0; gint text_bytelen = 0; gint cluster_start, cluster_end; gunichar unichr; PangoAttrList *attrlist = NULL; PangoAttribute *attr; PangoRectangle irect = {0, 0, 0, 0}; PangoRectangle lrect = {0, 0, 0, 0}; GdkColor mix; mix_colors (style->bg + GTK_STATE_NORMAL, style->fg + GTK_STATE_NORMAL, &mix, time); text = pango_layout_get_text (dialog->layout); g_return_if_fail (text != NULL); text_length = g_utf8_strlen (text, -1); text_bytelen = strlen (text); attrlist = pango_attr_list_new (); dialog->textrange[0] = 0; dialog->textrange[1] = text_bytelen; switch (anim_type) { case 0: /* Fade in */ attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue); attr->start_index = 0; attr->end_index = text_bytelen; pango_attr_list_insert (attrlist, attr); break; case 1: /* Fade in, spread */ attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue); attr->start_index = 0; attr->end_index = text_bytelen; pango_attr_list_change (attrlist, attr); ptr = text; cluster_start = 0; while ((unichr = g_utf8_get_char (ptr))) { ptr = g_utf8_next_char (ptr); cluster_end = (ptr - text); if (unichr == 0x200b) { lrect.width = (1.0 - time) * 15.0 * PANGO_SCALE + 0.5; attr = pango_attr_shape_new (&irect, &lrect); attr->start_index = cluster_start; attr->end_index = cluster_end; pango_attr_list_change (attrlist, attr); } cluster_start = cluster_end; } break; case 2: /* Fade in, sinewave */ attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue); attr->start_index = 0; attr->end_index = text_bytelen; pango_attr_list_change (attrlist, attr); ptr = text; cluster_start = 0; while ((unichr = g_utf8_get_char (ptr))) { if (unichr == 0x200b) { cluster_end = ptr - text; attr = pango_attr_rise_new ((1.0 -time) * 18000 * sin (4.0 * time + (float) letter_count * 0.7)); attr->start_index = cluster_start; attr->end_index = cluster_end; pango_attr_list_change (attrlist, attr); letter_count++; cluster_start = cluster_end; } ptr = g_utf8_next_char (ptr); } break; case 3: /* letterwise Fade in */ ptr = text; letter_count = 0; cluster_start = 0; while ((unichr = g_utf8_get_char (ptr))) { gint border = (text_length + 15) * time - 15; gdouble pos; if (letter_count < border) pos = 0; else if (letter_count > border + 15) pos = 1; else pos = ((gdouble) (letter_count - border)) / 15; mix_colors (style->fg + GTK_STATE_NORMAL, style->bg + GTK_STATE_NORMAL, &mix, pos); ptr = g_utf8_next_char (ptr); cluster_end = ptr - text; attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue); attr->start_index = cluster_start; attr->end_index = cluster_end; pango_attr_list_change (attrlist, attr); if (pos < 1.0) dialog->textrange[1] = cluster_end; letter_count++; cluster_start = cluster_end; } break; default: g_printerr ("Unknown animation type %d\n", anim_type); } pango_layout_set_attributes (dialog->layout, attrlist); pango_attr_list_unref (attrlist); }