; Improve commentary in xdisp.c

* src/xdisp.c: Add to the commentary the description of
stop_charpos, and how it is used during iteration.
This commit is contained in:
Eli Zaretskii 2019-08-17 11:02:52 +03:00
parent 15de1d1133
commit 3a04be2005

View file

@ -152,6 +152,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
description of the environment in which the text is to be description of the environment in which the text is to be
displayed. But this is too early, read on. displayed. But this is too early, read on.
Iteration over buffer and strings.
Characters and pixmaps displayed for a range of buffer text depend Characters and pixmaps displayed for a range of buffer text depend
on various settings of buffers and windows, on overlays and text on various settings of buffers and windows, on overlays and text
properties, on display tables, on selective display. The good news properties, on display tables, on selective display. The good news
@ -176,6 +178,46 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
current X and Y position, and lots of other stuff you can better current X and Y position, and lots of other stuff you can better
see in dispextern.h. see in dispextern.h.
The "stop position".
Some of the fields maintained by the iterator change relatively
infrequently. These include the face of the characters, whether
text is invisible, the object (buffer or display or overlay string)
being iterated, character composition info, etc. For any given
buffer or string position, these sources of information that
affects the display can be determined by calling the appropriate
primitives, such as Fnext_single_property_change, but both these
calls and the processing of their return values is relatively
expensive. To optimize redisplay, the display engine checks these
sources of display information only when needed. To that end, it
always maintains the position of the next place where it must stop
and re-examine all those potential sources. This is called "stop
position" and is stored in the stop_charpos field of the iterator.
The stop position is updated by compute_stop_pos, which is called
whenever the iteration reaches the current stop position and
processes it. Processing a stop position is done by handle_stop,
which invokes a series of handlers, one each for every potential
source of display-related information; see the it_props array for
those handlers. For example, one handler is handle_face_prop,
which detects changes in face properties, and supplies the face ID
that the iterator will use for all the glyphs it generates up to
the next stop position; this face ID is the result of realizing the
face specified by the relevant text properties at this position.
Each handler called by handle_stop processes the sources of display
information for which it is "responsible", and returns a value
which tells handle_stop what to do next.
Once handle_stop returns, the information it stores in the iterator
fields will not be refreshed until the iteration reaches the next
stop position, which is computed by compute_stop_pos called at the
end of handle_stop. compute_stop_pos examines the buffer's or
string's interval tree to determine where the text properties
change, finds the next position where overlays and character
composition can change, and stores in stop_charpos the closest
position where any of these factors should be reconsider.
Producing glyphs.
Glyphs in a desired matrix are normally constructed in a loop Glyphs in a desired matrix are normally constructed in a loop
calling get_next_display_element and then PRODUCE_GLYPHS. The call calling get_next_display_element and then PRODUCE_GLYPHS. The call
to PRODUCE_GLYPHS will fill the iterator structure with pixel to PRODUCE_GLYPHS will fill the iterator structure with pixel
@ -191,23 +233,28 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
Frame matrices. Frame matrices.
That just couldn't be all, could it? What about terminal types not That just couldn't be all, could it? What about terminal types not
supporting operations on sub-windows of the screen? To update the supporting operations on sub-windows of the screen (a.k.a. "TTY" or
display on such a terminal, window-based glyph matrices are not "text-mode terminal")? To update the display on such a terminal,
well suited. To be able to reuse part of the display (scrolling window-based glyph matrices are not well suited. To be able to
lines up and down), we must instead have a view of the whole reuse part of the display (scrolling lines up and down), we must
screen. This is what `frame matrices' are for. They are a trick. instead have a view of the whole screen. This is what `frame
matrices' are for. They are a trick.
Frames on terminals like above have a glyph pool. Windows on such Frames on text terminals have a glyph pool. Windows on such a
a frame sub-allocate their glyph memory from their frame's glyph frame sub-allocate their glyph memory from their frame's glyph
pool. The frame itself is given its own glyph matrices. By pool. The frame itself is given its own glyph matrices. By
coincidence---or maybe something else---rows in window glyph coincidence---or maybe something else---rows in window glyph
matrices are slices of corresponding rows in frame matrices. Thus matrices are slices of corresponding rows in frame matrices. Thus
writing to window matrices implicitly updates a frame matrix which writing to window matrices implicitly updates a frame matrix which
provides us with the view of the whole screen that we originally provides us with the view of the whole screen that we originally
wanted to have without having to move many bytes around. To be wanted to have without having to move many bytes around. Then
honest, there is a little bit more done, but not much more. If you updating all the visible windows on text-terminal frames is done by
plan to extend that code, take a look at dispnew.c. The function using the frame matrices, which allows frame-global optimization of
build_frame_matrix is a good starting point. what is actually written to the glass.
To be honest, there is a little bit more done, but not much more.
If you plan to extend that code, take a look at dispnew.c. The
function build_frame_matrix is a good starting point.
Bidirectional display. Bidirectional display.
@ -220,9 +267,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
concerned, the effect of calling bidi_move_to_visually_next, the concerned, the effect of calling bidi_move_to_visually_next, the
main interface of the reordering engine, is that the iterator gets main interface of the reordering engine, is that the iterator gets
magically placed on the buffer or string position that is to be magically placed on the buffer or string position that is to be
displayed next. In other words, a linear iteration through the displayed next in the visual order. In other words, a linear
buffer/string is replaced with a non-linear one. All the rest of iteration through the buffer/string is replaced with a non-linear
the redisplay is oblivious to the bidi reordering. one. All the rest of the redisplay is oblivious to the bidi
reordering.
Well, almost oblivious---there are still complications, most of Well, almost oblivious---there are still complications, most of
them due to the fact that buffer and string positions no longer them due to the fact that buffer and string positions no longer
@ -231,7 +279,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
monotonously changing with vertical positions. Also, accounting monotonously changing with vertical positions. Also, accounting
for face changes, overlays, etc. becomes more complex because for face changes, overlays, etc. becomes more complex because
non-linear iteration could potentially skip many positions with non-linear iteration could potentially skip many positions with
changes, and then cross them again on the way back... changes, and then cross them again on the way back (see
handle_stop_backwards)...
One other prominent effect of bidirectional display is that some One other prominent effect of bidirectional display is that some
paragraphs of text need to be displayed starting at the right paragraphs of text need to be displayed starting at the right
@ -252,7 +301,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
This way, the terminal-specific back-end can still draw the glyphs This way, the terminal-specific back-end can still draw the glyphs
left to right, even for R2L lines. left to right, even for R2L lines.
Bidirectional display and character compositions Bidirectional display and character compositions.
Some scripts cannot be displayed by drawing each character Some scripts cannot be displayed by drawing each character
individually, because adjacent characters change each other's shape individually, because adjacent characters change each other's shape
@ -272,15 +321,15 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
Each of these grapheme clusters is then delivered to PRODUCE_GLYPHS Each of these grapheme clusters is then delivered to PRODUCE_GLYPHS
in the direction corresponding to the current bidi scan direction in the direction corresponding to the current bidi scan direction
(recorded in the scan_dir member of the `struct bidi_it' object (recorded in the scan_dir member of the `struct bidi_it' object
that is part of the buffer iterator). In particular, if the bidi that is part of the iterator). In particular, if the bidi iterator
iterator currently scans the buffer backwards, the grapheme currently scans the buffer backwards, the grapheme clusters are
clusters are delivered back to front. This reorders the grapheme delivered back to front. This reorders the grapheme clusters as
clusters as appropriate for the current bidi context. Note that appropriate for the current bidi context. Note that this means
this means that the grapheme clusters are always stored in the that the grapheme clusters are always stored in the LGSTRING object
LGSTRING object (see composite.c) in the logical order. (see composite.c) in the logical order.
Moving an iterator in bidirectional text Moving an iterator in bidirectional text
without producing glyphs without producing glyphs.
Note one important detail mentioned above: that the bidi reordering Note one important detail mentioned above: that the bidi reordering
engine, driven by the iterator, produces characters in R2L rows engine, driven by the iterator, produces characters in R2L rows