Ejemplo n.º 1
0
static VALUE
layout_iter_get_layout_extents(VALUE self)
{
    PangoRectangle ink_rect, logical_rect;

    pango_layout_iter_get_layout_extents(_SELF(self), &ink_rect, &logical_rect);

    return rb_assoc_new(BOXED2RVAL(&ink_rect, PANGO_TYPE_RECTANGLE),
                        BOXED2RVAL(&logical_rect, PANGO_TYPE_RECTANGLE));
}
Ejemplo n.º 2
0
static void
render_para (GdkDrawable        *drawable,
             GtkTextRenderState *render_state,
             GtkTextLineDisplay *line_display,
             /* Top-left corner of paragraph including all margins */
             int                 x,
             int                 y,
             int                 selection_start_index,
             int                 selection_end_index,
             GList             **widgets)
{
  GSList *shaped_pointer = line_display->shaped_objects;
  PangoLayout *layout = line_display->layout;
  int byte_offset = 0;
  PangoLayoutIter *iter;
  PangoRectangle layout_logical;
  int screen_width;
  GdkGC *fg_gc, *bg_gc;
  gint state;
  
  gboolean first = TRUE;

  iter = pango_layout_get_iter (layout);

  pango_layout_iter_get_layout_extents (iter, NULL, &layout_logical);

  /* Adjust for margins */
  
  layout_logical.x += line_display->x_offset * PANGO_SCALE;
  layout_logical.y += line_display->top_margin * PANGO_SCALE;

  screen_width = line_display->total_width;
  
  if (GTK_WIDGET_HAS_FOCUS (render_state->widget))
    state = GTK_STATE_SELECTED;
  else
    state = GTK_STATE_ACTIVE;

  fg_gc = render_state->widget->style->text_gc [state];
  bg_gc = render_state->widget->style->base_gc [state];

  do
    {
      PangoLayoutLine *line = pango_layout_iter_get_line (iter);
      int selection_y, selection_height;
      int first_y, last_y;
      PangoRectangle line_rect;
      int baseline;
      
      pango_layout_iter_get_line_extents (iter, NULL, &line_rect);
      baseline = pango_layout_iter_get_baseline (iter);
      pango_layout_iter_get_line_yrange (iter, &first_y, &last_y);
      
      /* Adjust for margins */

      line_rect.x += line_display->x_offset * PANGO_SCALE;
      line_rect.y += line_display->top_margin * PANGO_SCALE;
      baseline += line_display->top_margin * PANGO_SCALE;

      /* Selection is the height of the line, plus top/bottom
       * margin if we're the first/last line
       */
      selection_y = y + PANGO_PIXELS (first_y) + line_display->top_margin;
      selection_height = PANGO_PIXELS (last_y) - PANGO_PIXELS (first_y);

      if (first)
        {
          selection_y -= line_display->top_margin;
          selection_height += line_display->top_margin;
        }
      
      if (pango_layout_iter_at_last_line (iter))
        selection_height += line_display->bottom_margin;
      
      first = FALSE;

      if (selection_start_index < byte_offset &&
          selection_end_index > line->length + byte_offset) /* All selected */
        {
          gdk_draw_rectangle (drawable,
                              bg_gc,
                              TRUE,
                              x + line_display->left_margin,
                              selection_y,
                              screen_width,
                              selection_height);

          render_layout_line (drawable, render_state, line, &shaped_pointer,
                              x + PANGO_PIXELS (line_rect.x),
                              y + PANGO_PIXELS (baseline),
                              TRUE,
                              widgets);
        }
      else
        {
          GSList *shaped_pointer_tmp = shaped_pointer;

          render_layout_line (drawable, render_state,
                              line, &shaped_pointer,
                              x + PANGO_PIXELS (line_rect.x),
                              y + PANGO_PIXELS (baseline),
                              FALSE,
                              widgets);

          if (selection_start_index <= byte_offset + line->length &&
              selection_end_index > byte_offset) /* Some selected */
            {
              GdkRegion *clip_region = get_selected_clip (render_state, layout, line,
                                                          x + line_display->x_offset,
                                                          selection_y,
                                                          selection_height,
                                                          selection_start_index, selection_end_index);
              gdk_gc_set_clip_region (fg_gc, clip_region);
              gdk_gc_set_clip_region (bg_gc, clip_region);

              gdk_draw_rectangle (drawable,
                                  bg_gc,
                                  TRUE,
                                  x + PANGO_PIXELS (line_rect.x),
                                  selection_y,
                                  PANGO_PIXELS (line_rect.width),
                                  selection_height);

              render_layout_line (drawable, render_state, line, &shaped_pointer_tmp,
                                  x + PANGO_PIXELS (line_rect.x),
                                  y + PANGO_PIXELS (baseline),
                                  TRUE,
                                  widgets);

              gdk_gc_set_clip_region (fg_gc, NULL);
              gdk_gc_set_clip_region (bg_gc, NULL);

              gdk_region_destroy (clip_region);

              /* Paint in the ends of the line */
              if (line_rect.x > line_display->left_margin * PANGO_SCALE &&
                  ((line_display->direction == GTK_TEXT_DIR_LTR && selection_start_index < byte_offset) ||
                   (line_display->direction == GTK_TEXT_DIR_RTL && selection_end_index > byte_offset + line->length)))
                {
                  gdk_draw_rectangle (drawable,
                                      bg_gc,
                                      TRUE,
                                      x + line_display->left_margin,
                                      selection_y,
                                      PANGO_PIXELS (line_rect.x) - line_display->left_margin,
                                      selection_height);
                }

              if (line_rect.x + line_rect.width <
                  (screen_width + line_display->left_margin) * PANGO_SCALE &&
                  ((line_display->direction == GTK_TEXT_DIR_LTR && selection_end_index > byte_offset + line->length) ||
                   (line_display->direction == GTK_TEXT_DIR_RTL && selection_start_index < byte_offset)))
                {
                  int nonlayout_width;

                  nonlayout_width =
                    line_display->left_margin + screen_width -
                    PANGO_PIXELS (line_rect.x) - PANGO_PIXELS (line_rect.width);

                  gdk_draw_rectangle (drawable,
                                      bg_gc,
                                      TRUE,
                                      x + PANGO_PIXELS (line_rect.x) + PANGO_PIXELS (line_rect.width),
                                      selection_y,
                                      nonlayout_width,
                                      selection_height);
                }
            }
        }

      byte_offset += line->length;
    }
  while (pango_layout_iter_next_line (iter));

  pango_layout_iter_free (iter);
}