emacs-devel
[Top][All Lists]
Advanced

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

Re: Question about display engine


From: martin rudalics
Subject: Re: Question about display engine
Date: Tue, 13 Aug 2019 10:17:32 +0200

>> 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.

In an earlier mail I labelled the display engine as "face agnostic" so
I am very well aware of that.  What I tried to point out (and failed)
so far is precisely how to work around that issue.

> 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?

It's the last face whose (1) :underline attribute is merged in _and_
whose (2) :extend attribute is set (nil or non-nil) that determines
whether the underline extends or not.  Whether that is what the users
expect is beyond my knowledge.  We can only try to provide a fairly
consistent way of specifying it.

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

Consider a user who sets the :extend attribute to non-nil for the
'default' face and wants a 'link' background to not extend to the end
of line.  Such a user would want to set the :extend attribute of the
'link' face to nil to get the desired effect.

> You seem to assume that the iterator examines faces at every buffer
> position it passes, and in particular on the newline at EOL.

I certainly do not assume such a thing.  But when trying to find out
how face attributes are merged and realized, face_at_buffer_position
was the first point of reference where I found that (and I still don't
know a better one).

> 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.

That's exactly what I expected but did not find immediately.  If you
tell me where to look for that (Fnext_single_property_change _is_
called by face_at_buffer_position) "examine faces where they change"
and in particular where a :background change is found and applied, I
probably could tell you more.

> 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.

When face_at_buffer_position puts some 'background' value into that
single attribute vector, it can simply set an 'extend_background' bit
in that vector which tells the display engine whether the background
specified by that vector shall be extended or not.  Note that that
'extend_background' bit would be left alone when the face specifying
:background does not also specify :extend.  In that case the value of
:extend of the last face merged in that specified both would persist.

> 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?)

I never show continuation lines (with exception of the minibuffer
where I have no choice) but I suppose we should apply the extension
there as well.  Think of the region spanning several continued lines.

>   . modify face_at_buffer_position and its subroutines to behave
>     specially when called on a newline,

I strongly doubt that this "called on a newline" is needed.  Setting
the 'extend_background' indicator is strongly tied to the last setting
of the 'background' indicator in the attribute vector as done by the
face merging algorithm.

> 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.

If all these were really necessary, I'd never vote for such a change.

martin



reply via email to

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