Ejemplo n.º 1
0
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;
    }
}
Ejemplo n.º 2
0
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);
}