static void render_layout_line (GdkDrawable *drawable, GtkTextRenderState *render_state, PangoLayoutLine *line, GSList **shaped_pointer, int x, int y, gboolean selected, GList **widgets) { GSList *tmp_list = line->runs; PangoRectangle overall_rect; PangoRectangle logical_rect; PangoRectangle ink_rect; gint x_off = 0; GdkGC *fg_gc; pango_layout_line_get_extents (line, NULL, &overall_rect); while (tmp_list) { PangoLayoutRun *run = tmp_list->data; GtkTextAppearance *appearance; gint risen_y; gint shaped_width_pixels = 0; gboolean need_ink = FALSE; tmp_list = tmp_list->next; get_item_properties (run->item, &appearance); g_assert (appearance != NULL); risen_y = y - PANGO_PIXELS (appearance->rise); if (selected) { if (GTK_WIDGET_HAS_FOCUS (render_state->widget)) fg_gc = render_state->widget->style->text_gc[GTK_STATE_SELECTED]; else fg_gc = render_state->widget->style->text_gc [GTK_STATE_ACTIVE]; } else { gtk_text_render_state_update (render_state, appearance); fg_gc = render_state->fg_gc; } if (appearance->underline != PANGO_UNDERLINE_NONE || appearance->strikethrough) need_ink = TRUE; if (appearance->is_text) { if (need_ink) pango_glyph_string_extents (run->glyphs, run->item->analysis.font, &ink_rect, &logical_rect); else pango_glyph_string_extents (run->glyphs, run->item->analysis.font, NULL, &logical_rect); } else { if (need_ink) get_shape_extents (run, &ink_rect, &logical_rect); else get_shape_extents (run, NULL, &logical_rect); } if (appearance->draw_bg && !selected) gdk_draw_rectangle (drawable, render_state->bg_gc, TRUE, x + PANGO_PIXELS (x_off) + PANGO_PIXELS (logical_rect.x), risen_y + PANGO_PIXELS (logical_rect.y), PANGO_PIXELS (logical_rect.width), PANGO_PIXELS (logical_rect.height)); if (appearance->is_text) gdk_draw_glyphs (drawable, fg_gc, run->item->analysis.font, x + PANGO_PIXELS (x_off), risen_y, run->glyphs); else { GObject *shaped = (*shaped_pointer)->data; *shaped_pointer = (*shaped_pointer)->next; if (shaped == NULL) { /* This happens if we have an empty widget anchor. Draw * something empty-looking. */ GdkRectangle shape_rect, draw_rect; shape_rect.x = x + x_off / PANGO_SCALE; shape_rect.y = risen_y - PANGO_PIXELS (logical_rect.height); shape_rect.width = PANGO_PIXELS (logical_rect.width); shape_rect.height = PANGO_PIXELS (logical_rect.height); if (gdk_rectangle_intersect (&shape_rect, &render_state->clip_rect, &draw_rect)) { gdk_draw_rectangle (drawable, render_state->fg_gc, FALSE, shape_rect.x, shape_rect.y, shape_rect.width, shape_rect.height); gdk_draw_line (drawable, render_state->fg_gc, shape_rect.x, shape_rect.y, shape_rect.x + shape_rect.width, shape_rect.y + shape_rect.height); gdk_draw_line (drawable, render_state->fg_gc, shape_rect.x + shape_rect.width, shape_rect.y, shape_rect.x, shape_rect.y + shape_rect.height); } shaped_width_pixels = shape_rect.width; } else if (GDK_IS_PIXBUF (shaped)) { gint width, height; GdkRectangle pixbuf_rect, draw_rect; GdkPixbuf *pixbuf; pixbuf = GDK_PIXBUF (shaped); width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); pixbuf_rect.x = x + x_off / PANGO_SCALE; pixbuf_rect.y = risen_y - height; pixbuf_rect.width = width; pixbuf_rect.height = height; if (gdk_rectangle_intersect (&pixbuf_rect, &render_state->clip_rect, &draw_rect)) { gdk_draw_pixbuf (drawable, render_state->fg_gc, pixbuf, draw_rect.x - pixbuf_rect.x, draw_rect.y - pixbuf_rect.y, draw_rect.x, draw_rect.y, draw_rect.width, draw_rect.height, GDK_RGB_DITHER_NORMAL, 0, 0); } shaped_width_pixels = width; } else if (GTK_IS_WIDGET (shaped)) { GtkWidget *widget; widget = GTK_WIDGET (shaped); shaped_width_pixels = widget->allocation.width; if (widgets) { g_object_ref (widget); *widgets = g_list_prepend (*widgets, widget); } } else g_assert_not_reached (); /* not a pixbuf or widget */ } switch (appearance->underline) { case PANGO_UNDERLINE_NONE: break; case PANGO_UNDERLINE_DOUBLE: g_assert (need_ink); gdk_draw_line (drawable, fg_gc, x + (x_off + ink_rect.x) / PANGO_SCALE - 1, risen_y + 3, x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, risen_y + 3); /* Fall through */ case PANGO_UNDERLINE_SINGLE: g_assert (need_ink); gdk_draw_line (drawable, fg_gc, x + (x_off + ink_rect.x) / PANGO_SCALE - 1, risen_y + 1, x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, risen_y + 1); break; case PANGO_UNDERLINE_LOW: g_assert (need_ink); gdk_draw_line (drawable, fg_gc, x + (x_off + ink_rect.x) / PANGO_SCALE - 1, risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 1, x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 1); break; } if (appearance->strikethrough) { gint strikethrough_y = risen_y + (0.3 * logical_rect.y) / PANGO_SCALE; g_assert (need_ink); gdk_draw_line (drawable, fg_gc, x + (x_off + ink_rect.x) / PANGO_SCALE - 1, strikethrough_y, x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, strikethrough_y); } if (appearance->is_text) x_off += logical_rect.width; else x_off += shaped_width_pixels * PANGO_SCALE; } }
static void print_pango_layout_line (GnomePrintContext *gpc, PangoLayoutLine *line) { GSList *tmp_list = line->runs; PangoRectangle overall_rect; PangoRectangle logical_rect; PangoRectangle ink_rect; gint x_off = 0; gnome_print_gsave (gpc); current_point_to_origin (gpc); pango_layout_line_get_extents (line, NULL, &overall_rect); while (tmp_list) { ItemProperties properties; PangoLayoutRun *run = tmp_list->data; tmp_list = tmp_list->next; get_item_properties (run->item, &properties); if (properties.shape_logical_rect) { x_off += properties.shape_logical_rect->width; continue; } gnome_print_gsave (gpc); translate (gpc, x_off, properties.rise); gnome_print_moveto (gpc, 0, 0); if (properties.uline == PANGO_UNDERLINE_NONE && !properties.strikethrough) pango_glyph_string_extents (run->glyphs, run->item->analysis.font, NULL, &logical_rect); else pango_glyph_string_extents (run->glyphs, run->item->analysis.font, &ink_rect, &logical_rect); if (properties.bg_color) { gnome_print_gsave (gpc); gnome_print_setrgbcolor (gpc, (gdouble) properties.bg_color->red / 0xFFFF, (gdouble) properties.bg_color->green / 0xFFFF, (gdouble) properties.bg_color->blue / 0xFFFF); rect_filled (gpc, logical_rect.x, - overall_rect.y - overall_rect.height, logical_rect.width, overall_rect.height); gnome_print_grestore (gpc); } if (properties.fg_color) { gnome_print_setrgbcolor (gpc, (gdouble) properties.fg_color->red / 0xFFFF, (gdouble) properties.fg_color->green / 0xFFFF, (gdouble) properties.fg_color->blue / 0xFFFF); } gnome_print_pango_glyph_string (gpc, run->item->analysis.font, run->glyphs); if (properties.uline != PANGO_UNDERLINE_NONE || properties.strikethrough) { PangoFontMetrics *metrics = pango_font_get_metrics (run->item->analysis.font, run->item->analysis.language); if (properties.uline != PANGO_UNDERLINE_NONE) draw_underline (gpc, metrics, properties.uline, ink_rect.x, ink_rect.width, ink_rect.y + ink_rect.height); if (properties.strikethrough) draw_strikethrough (gpc, metrics, ink_rect.x, ink_rect.width); pango_font_metrics_unref (metrics); } gnome_print_grestore (gpc); x_off += logical_rect.width; } gnome_print_grestore (gpc); }