emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Question about display engine


From: Eli Zaretskii
Subject: Re: Question about display engine
Date: Mon, 12 Aug 2019 18:29:28 +0300

> Cc: address@hidden, address@hidden
> From: martin rudalics <address@hidden>
> Date: Mon, 12 Aug 2019 10:59:52 +0200
> 
>  >> Answering this question should not be the task of a (face agnostic)
>  >> display engine.  The face merging algorithm would have to decide
>  >> whether the :extend attribute of the winning face should cause an
>  >> extension of any attribute specified by that face.
>  >
>  > What is the "winning face" in this context?
> 
> IIUC the last one found by face_at_buffer_position that explicitly
> specified a value for the attribute in question.  That is, the face
> whose attribute is actually used by the display engine.

Nitpicking: the display engine has no idea whose attributes it is
using, see below.

>  > Not necessarily true: two or more faces could specify the same value
>  > of a particular attribute, including background and underlining.  The
>  > :extend attribute could be different in some of these faces.
> 
> Suppose the iterator is at a newline character within some highlighted
> text within the region and wants to know the :background attribute at
> that position.
> 
> With a face-based solution, face_at_buffer_position will have looked
> for a :background value provided by the default face, the highlight
> face and the region face, in this order.  The value of the :extend
> attribute provided by the last face found that way is passed (in some
> extend_background variable I presume) to the display engine so the
> latter can determine whether the background shall be extended to the
> window edge or not.

If two or more faces of those merged specify :underline, and only one
of them has a non-nil :extend, will extending the underline do what
the users expect?

(And shouldn't we simply disregard entirely a face whose :extend
attribute is nil?  What can such a face possibly contribute in this
case?)

> With an attribute-based solution, face_at_buffer_position will have
> provided an appropriate value when the last face "found that way" is a
> member of the 'extend-background' Lisp variable.
> 
> A similar approach would be used to decide whether the rest of the
> line should be underlined, overlined, boxed, appear in inverse-video
> or whatever someone considers important (I suppose that none of these
> should ever extend).

You seem to assume that the iterator examines faces at every buffer
position it passes, and in particular on the newline at EOL.  But
that's not what happens, because examining and merging faces is
expensive, so Emacs avoids doing that unless necessary.  We only
examine faces where they change, and use next-single-property-change
to find the next position where we should again examine the faces.

In addition, face_at_buffer_position doesn't look for face attributes
one by one.  Instead, it finds all the source of the 'face' property
that are in effect at the given position -- the default face, the face
from text properties, and from all the overlays at that position --
and merges these attributes into a single attribute vector.  Then it
looks up a realized face with identical attributes, or realizes a new
face if no such face exists.  Thereafter, the iterator just uses that
face until the next checkpoint.  IOW, face_at_buffer_position returns
an ID of a realized (i.e. fully specified) face created by merging
several relevant sources of face information, and that realized face
has no references to the names of the individual faces from which it
was created, nor any memory of which non-unspecified attributes came
from which face source.

So to implement something like above, we will have to:

 . force face merging when we get to a newline (btw, what about
   continuation lines in this context? do we apply the extension logic
   to them as well?)
 . modify face_at_buffer_position and its subroutines to behave
   specially when called on a newline, and decide whether to merge or
   not merge attributes based on whatever data structures describe the
   preferences for extending those attributes; this would go at least
   two levels below face_at_buffer_position
 . do something similar in face_at_string_position, for display and
   overlay strings with embedded newlines

Sounds like fun project.  Volunteers are welcome.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]