unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* variable line spacing
@ 2002-03-10  9:31 Werner LEMBERG
  2002-03-10 14:54 ` Gerd Moellmann
  0 siblings, 1 reply; 2+ messages in thread
From: Werner LEMBERG @ 2002-03-10  9:31 UTC (permalink / raw)
  Cc: gerd


Here is my preliminary patch for implementing variable line spacing.

  . It defines a buffer/frame variable `line-spacing-no-overlap'.  If
    non-nil, increase line space for lines with over-sized ascents
    and/or descents.

    Currently, it automatically increases the line spacing by one
    pixel above and below for such lines.  Eventually I will make the
    amount configurable.

    Another question: Shall this be a user variable?  I wonder why
    `line-spacing' itself isn't a user variable...

  . I tried to improve the drawing of extra line spacing (set with the
    `line-spacing' variable).  Currently, it looks very ugly if
    line-spacing is set to a large value since it is only applied to
    the descender.  My fix tries to add extra line spacing to both the
    ascent and the descent.

    Nevertheless, my solution isn't completely satisfactory.
    Cf. the places marked with `XXX'.  Gerd, any idea how to handle
    this gracefully?


Please comment.


    Werner


PS: The changes to macfns.c are missing in the patch.

======================================================================

Index: src/buffer.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/buffer.c,v
retrieving revision 1.380
diff -u -r1.380 buffer.c
--- src/buffer.c	4 Mar 2002 23:20:06 -0000	1.380
+++ src/buffer.c	7 Mar 2002 05:39:32 -0000
@@ -646,6 +646,7 @@
   b->enable_multibyte_characters = buffer_defaults.enable_multibyte_characters;
   b->cursor_type = buffer_defaults.cursor_type;
   b->extra_line_spacing = buffer_defaults.extra_line_spacing;
+  b->line_spacing_no_overlap = buffer_defaults.line_spacing_no_overlap;
 
   b->display_error_modiff = 0;
 }
@@ -4824,6 +4825,7 @@
   buffer_defaults.direction_reversed = Qnil;
   buffer_defaults.cursor_type = Qt;
   buffer_defaults.extra_line_spacing = Qnil;
+  buffer_defaults.line_spacing_no_overlap = Qnil;
 
 #ifdef DOS_NT
   buffer_defaults.buffer_file_type = Qnil; /* TEXT */
@@ -4905,6 +4907,7 @@
   XSETFASTINT (buffer_local_flags.header_line_format, idx); ++idx;
   XSETFASTINT (buffer_local_flags.cursor_type, idx); ++idx;
   XSETFASTINT (buffer_local_flags.extra_line_spacing, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.line_spacing_no_overlap, idx); ++idx;
 
   /* Need more room? */
   if (idx >= MAX_PER_BUFFER_VARS)
@@ -5082,6 +5085,11 @@
 		     doc: /* Default value of `line-spacing' for buffers that don't override it.
 This is the same as (default-value 'line-spacing).  */);
 
+  DEFVAR_LISP_NOPRO ("default-line-spacing-no-overlap",
+		     &buffer_defaults.line_spacing_no_overlap,
+		     doc: /* Default value of `line-spacing-no-overlap' for buffers that don't override it.
+This is the same as (default-value 'line-spacing-no-overlap).  */);
+
   DEFVAR_LISP_NOPRO ("default-abbrev-mode",
 		     &buffer_defaults.abbrev_mode,
 		     doc: /* Default value of `abbrev-mode' for buffers that do not override it.
@@ -5613,6 +5621,16 @@
 		     &current_buffer->extra_line_spacing, Qnil,
 		     doc: /* Additional space to put between lines when displaying a buffer.
 The space is measured in pixels, and put below lines on window systems.  */);
+
+  DEFVAR_PER_BUFFER ("line-spacing-no-overlap",
+		     &current_buffer->line_spacing_no_overlap, Qnil,
+		     doc: /* Non-nil means glyph ascenders and descenders won't overlap.
+By default, Emacs doesn't increase the line space if it encounters
+glyphs that draw vertically outside of their logical bounds.  This
+can cause overlapping, making the affected glyphs unreadable.
+
+Contrary to `line-spacing', only lines with over-sized glyphs are
+moved apart; other lines are not affected.  */);
 
   DEFVAR_LISP ("kill-buffer-query-functions", &Vkill_buffer_query_functions,
 	       doc: /* List of functions called with no args to query before killing a buffer.  */);
Index: src/buffer.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/buffer.h,v
retrieving revision 1.85
diff -u -r1.85 buffer.h
--- src/buffer.h	10 Jan 2002 11:13:17 -0000	1.85
+++ src/buffer.h	7 Mar 2002 05:39:34 -0000
@@ -743,6 +743,10 @@
   /* An integer > 0 means put that number of pixels below text lines
      in the display of this buffer.  */
   Lisp_Object extra_line_spacing;
+
+  /* True if lines with vertically oversized glyphs should not
+     overlap.  */
+  Lisp_Object line_spacing_no_overlap;
 };
 
 \f
Index: src/dispextern.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/dispextern.h,v
retrieving revision 1.130
diff -u -r1.130 dispextern.h
--- src/dispextern.h	4 Mar 2002 23:41:00 -0000	1.130
+++ src/dispextern.h	7 Mar 2002 05:39:44 -0000
@@ -1780,8 +1780,12 @@
   int last_visible_y;
 
   /* Additional space in pixels between lines (for window systems
-     only.)  */
+     only).  */
   int extra_line_spacing;
+
+  /* 1 means lines with vertically oversized glyphs don't overlap
+     (for window systems only).  */
+  unsigned line_spacing_no_overlap_p : 1;
 
   /* If non-null, glyphs are produced in glyph_row with each call to
      produce_glyphs.  */
Index: src/frame.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/frame.h,v
retrieving revision 1.95
diff -u -r1.95 frame.h
--- src/frame.h	16 Feb 2002 23:54:04 -0000	1.95
+++ src/frame.h	7 Mar 2002 05:39:46 -0000
@@ -369,6 +369,10 @@
   /* Additional space to put between text lines on this frame.  */
   int extra_line_spacing;
 
+  /* 1 means lines with vertically oversized glyphs don't overlap
+     (for window systems only).  */
+  unsigned line_spacing_no_overlap_p : 1;
+
   /* Set to non-zero in change_frame_size when size of frame changed
      Clear the frame in clear_garbaged_frames if set.  */
   unsigned resized_p : 1;
Index: src/w32fns.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/w32fns.c,v
retrieving revision 1.157
diff -u -r1.157 w32fns.c
--- src/w32fns.c	23 Feb 2002 18:14:06 -0000	1.157
+++ src/w32fns.c	7 Mar 2002 05:40:23 -0000
@@ -692,6 +692,8 @@
 /* TODO: Native Input Method support; see x_create_im.  */
 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_set_line_spacing_no_overlap P_ ((struct frame *, Lisp_Object,
+					       Lisp_Object));
 static void x_set_fullscreen P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
@@ -745,6 +747,7 @@
   {"tool-bar-lines", x_set_tool_bar_lines},
   {"screen-gamma", x_set_screen_gamma},
   {"line-spacing", x_set_line_spacing},
+  {"line-spacing-no-overlap", x_set_line_spacing_no_overlap},
   {"left-fringe", x_set_fringe_width},
   {"right-fringe", x_set_fringe_width},
   {"fullscreen", x_set_fullscreen},
@@ -2018,6 +2021,15 @@
 			    Fcons (new_value, Qnil)));
   if (FRAME_VISIBLE_P (f))
     redraw_frame (f);
+}
+
+
+static void
+x_set_line_spacing_no_overlap (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  f->line_spacing_no_overlap_p = !EQ (Qnil, arg);
 }
 
 
Index: src/xdisp.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xdisp.c,v
retrieving revision 1.735
diff -u -r1.735 xdisp.c
--- src/xdisp.c	6 Mar 2002 14:03:07 -0000	1.735
+++ src/xdisp.c	7 Mar 2002 05:41:00 -0000
@@ -1526,6 +1526,10 @@
 	it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
       else if (it->f->extra_line_spacing > 0)
 	it->extra_line_spacing = it->f->extra_line_spacing;
+
+      it->line_spacing_no_overlap_p
+	= (!NILP (current_buffer->line_spacing_no_overlap)
+	   || it->f->line_spacing_no_overlap_p);
     }
 
   /* If realized faces have been removed, e.g. because of face
@@ -10818,7 +10822,7 @@
 	return 0;
 
       IF_DEBUG (debug_method_add (w, "twu1"));
-      
+
       /* Display up to a row that can be reused.  The variable
 	 last_text_row is set to the last row displayed that displays
 	 text.  Note that it.vpos == 0 if or if not there is a
@@ -10827,7 +10831,14 @@
       first_row_y = it.current_y;
       w->cursor.vpos = -1;
       last_text_row = last_reused_text_row = NULL;
-      
+
+      /* XXX: Give up if we have some extra line spacing.  This is not the
+         correct solution, but I couldn't find out how add the ascent part
+         of the extra line spacing to the top row before scrolling (which
+         has been removed in `compute_line_metrics').  */
+      if (it.extra_line_spacing)
+	return 0;
+
       while (it.current_y < it.last_visible_y
 	     && IT_CHARPOS (it) < CHARPOS (start)
 	     && !fonts_changed_p)
@@ -11000,6 +11011,13 @@
       xassert (first_row_to_display->y < yb);
       init_to_row_start (&it, w, first_row_to_display);
 
+      /* XXX: Give up if we have some extra line spacing.  This is not the
+         correct solution, but I couldn't find out how remove the ascent
+         part of the extra line spacing in the top row after scrolling
+         (similar to `compute_line_metrics').  */
+      if (it.extra_line_spacing)
+	return 0;
+
       nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
 			- start_vpos);
       it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
@@ -12564,14 +12582,42 @@
       row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
 			    || MATRIX_ROW_OVERLAPS_PRED_P (row));
 
+      /* If `line_spacing_no_overlap_p' is true, make the row taller
+         for over-sized descents.  */
+      if (row->phys_height - row->phys_ascent > row->height - row->ascent
+	  && it->line_spacing_no_overlap_p)
+	row->height += (row->phys_height - row->phys_ascent)
+		       - (row->height - row->ascent)
+		       + 1;
+
+      /* Remove first line's ascent part of the extra line spacing */
+      if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix))
+	{
+	  row->ascent -= it->extra_line_spacing / 2;
+	  row->height -= it->extra_line_spacing / 2;
+	}
+
       /* If first line's physical ascent is larger than its logical
          ascent, use the physical ascent, and make the row taller.
-         This makes accented characters fully visible.  */
-      if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
-	  && row->phys_ascent > row->ascent)
+         This makes accented characters fully visible.
+         If `line_spacing_no_overlap_p' is true, do this for all
+         affected lines.  */
+      if (row->phys_ascent > row->ascent
+	  && (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
+	      || it->line_spacing_no_overlap_p))
 	{
 	  row->height += row->phys_ascent - row->ascent;
 	  row->ascent = row->phys_ascent;
+
+	  /* Similar to over-sized descents, we add one pixel if
+             `line_spacing_no_overlap_p' is true and we are not
+             in the first row.  */
+	  if (row != MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
+	      && it->line_spacing_no_overlap_p)
+	    {
+	      row->height += 1;
+	      row->ascent += 1;
+	    }
 	}
 
       /* Compute how much of the line is visible.  */
Index: src/xfns.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xfns.c,v
retrieving revision 1.540
diff -u -r1.540 xfns.c
--- src/xfns.c	3 Mar 2002 20:07:42 -0000	1.540
+++ src/xfns.c	7 Mar 2002 05:41:45 -0000
@@ -736,6 +736,8 @@
 static void x_disable_image P_ ((struct frame *, struct image *));
 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_set_line_spacing_no_overlap P_ ((struct frame *, Lisp_Object,
+					       Lisp_Object));
 static void x_set_wait_for_wm P_ ((struct frame *, Lisp_Object, Lisp_Object));
 static void x_set_fullscreen P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
@@ -808,6 +810,7 @@
   {"scroll-bar-background",	x_set_scroll_bar_background},
   {"screen-gamma",		x_set_screen_gamma},
   {"line-spacing",		x_set_line_spacing},
+  {"line-spacing-no-overlap",	x_set_line_spacing_no_overlap},
   {"left-fringe",		x_set_fringe_width},
   {"right-fringe",		x_set_fringe_width},
   {"wait-for-wm",		x_set_wait_for_wm},
@@ -1423,6 +1426,15 @@
 			    Fcons (new_value, Qnil)));
   if (FRAME_VISIBLE_P (f))
     redraw_frame (f);
+}
+
+
+static void
+x_set_line_spacing_no_overlap (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  f->line_spacing_no_overlap_p = !EQ (Qnil, arg);
 }
 
 
Index: src/xterm.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xterm.c,v
retrieving revision 1.710
diff -u -r1.710 xterm.c
--- src/xterm.c	4 Mar 2002 23:40:59 -0000	1.710
+++ src/xterm.c	7 Mar 2002 05:42:29 -0000
@@ -2323,8 +2323,9 @@
   xassert (it->ascent >= 0 && it->descent >= 0);
   if (it->area == TEXT_AREA)
     it->current_x += it->pixel_width;
-  
-  it->descent += it->extra_line_spacing;
+
+  it->ascent += it->extra_line_spacing / 2;
+  it->descent += it->extra_line_spacing - it->extra_line_spacing / 2;
   
   it->max_ascent = max (it->max_ascent, it->ascent);
   it->max_descent = max (it->max_descent, it->descent);

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/emacs-devel


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: variable line spacing
  2002-03-10  9:31 variable line spacing Werner LEMBERG
@ 2002-03-10 14:54 ` Gerd Moellmann
  0 siblings, 0 replies; 2+ messages in thread
From: Gerd Moellmann @ 2002-03-10 14:54 UTC (permalink / raw)
  Cc: emacs-devel

Werner LEMBERG <wl@gnu.org> writes:

>     Currently, it automatically increases the line spacing by one
>     pixel above and below for such lines.

Doesn't this mix up two functionalities?  It might be cleaner to
separate this into two issues: no overlapping lines, and additional
space between lines.

> Index: src/buffer.c
> ===================================================================
> RCS file: /cvsroot/emacs/emacs/src/buffer.c,v
> retrieving revision 1.380
> diff -u -r1.380 buffer.c
> --- src/buffer.c	4 Mar 2002 23:20:06 -0000	1.380
> +++ src/buffer.c	7 Mar 2002 05:39:32 -0000

[...]

> +static void
> +x_set_line_spacing_no_overlap (f, arg, oldval)
> +     struct frame *f;
> +     Lisp_Object arg, oldval;
> +{
> +  f->line_spacing_no_overlap_p = !EQ (Qnil, arg);
>  }

(Using NILP is preferred to EQ (Qnil, ...).)

> Index: src/xterm.c
> ===================================================================
> RCS file: /cvsroot/emacs/emacs/src/xterm.c,v
> retrieving revision 1.710
> diff -u -r1.710 xterm.c
> --- src/xterm.c	4 Mar 2002 23:40:59 -0000	1.710
> +++ src/xterm.c	7 Mar 2002 05:42:29 -0000
> @@ -2323,8 +2323,9 @@
>    xassert (it->ascent >= 0 && it->descent >= 0);
>    if (it->area == TEXT_AREA)
>      it->current_x += it->pixel_width;
> -  
> -  it->descent += it->extra_line_spacing;
> +
> +  it->ascent += it->extra_line_spacing / 2;
> +  it->descent += it->extra_line_spacing - it->extra_line_spacing / 2;
>    
>    it->max_ascent = max (it->max_ascent, it->ascent);
>    it->max_descent = max (it->max_descent, it->descent);

Hm, now that I see the code, I think it is more correct to do the line
height changes exclusively here, also for the non-overlapping case.
The reason for this is that some computations over text (the move_*
functions in xdisp.c) need to know line heights, but there are no
glyph rows, only the iterator.  That's also the reason why I did the
extra_line_spacing stuff here.  Sorry for setting you on the wrong
track; I'm apparently already swapping out the very basics of what
I coded.

If you compute IT's ascent, descent, max_ascent, and max_descent from
the physical ascent and descent in x_produce_glyhs, this prevents
overlapping because these values are used for the height and ascent of
glyph rows.  And the code in compute_line_metrics increasing the first
row's height doesn't run then, because there is no overlap.  There
should also be no need to do anything special in other functions in
xdisp.c or xterm.c, AFAIR.

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/emacs-devel


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-03-10 14:54 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-03-10  9:31 variable line spacing Werner LEMBERG
2002-03-10 14:54 ` Gerd Moellmann

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).