Dear Joris, (and texmacs-dev)
This week I have been playing with your experimental style rewriter
(src/Style, --enable-experimental), aiming at the goal you describe in
the todo list: the rewriter's output should feed the typesetter. While
comparing the two outputs pixel by pixel, I ran into the markers of the
concatenator. Fixing them properly touches the normal typesetter, so I
would like your advice before going further. And if you find the time
to look at what I did with the rewriter, I would be very grateful.
1. THE PROBLEM: MARKERS CHANGE THE LAYOUT
concater_rep::marker puts an empty text_box around every macro call,
every argument and every with. It is a place for the cursor, typed
MARKER_ITEM, in cmr at the script size. Its extents are not empty: it
goes from the baseline to the cmr x-height. So the same markup does not
typeset the same way when it is written out and when a macro produces
it. I tested this systematically: wrap pieces of a document in an
identity macro, print both versions, compare. These are the channels I
found:
- Italic corrections: italic_correct and italic_restore are not
symmetric. Restore asks the concat box again for its corrections, but
those depend on extents that italic_correct has just changed, so a box
with zero-width markers at its edges stays wider. A subscript given
through <arg> in Termes was 0.6 pt off.
- Script levels: the concat box's sub_lo_base, sup_lo_base and the other
limits take the min or max over all children, markers included, in
cmr.
* T<with|color|brown|<rsub|E>> puts the E 3 pt higher than
T<rsub|E>. This is your beamer logo <TeXmacs*>.
* <apply|cE><rsub|N> in witness.tm put the N 1.9 pt higher than the
same markup written out.
- Markers as script bases: a marker can become the base of a script. A
macro <st> for <rsup|o> at the start of a table cell is placed 1 pt
away from <rsup|o> written out.
- Accent and shape: extended_shape and top_accent (in Upsilon, not upstream)
test N(bs)==1, so a single glyph glued to markers loses its accent
position.
- Spaces at the end: with markers after the last item, its space counts
(typeset_as_concat, lazy_paragraph line_print and query).
print (space) puts a space on the last item even when that item is a
marker. kill_spaces stops at markers.
- Marker height: lines or boxes holding only markers get the x-height of
cmr. This is also the only reason cmr is loaded in documents that
don't use it.
2. WHAT I DID
- Italic corrections: italic_restore now undoes exactly what
italic_correct did; the corrections are kept, not asked for again.
- Zero extents: markers have zero extents and use the current font
instead of cmr. The cursor still gets its height from the font in
text_box_rep::find_cursor.
- Groups of boxes: a concat box leaves its markers out of its heights
and ink. It keeps them in its horizontal extents: my first version
also left them out of those, which moved equation numbers after a
tab. Its script levels, accent and shape are those of its single
non-marker box.
- Scripts: a marker is never the base of a script; a script after
markers takes the base the written-out markup would have, or none. The
italic correction goes on the item before the markers.
- Spaces: the spacing rules ignore trailing markers. kill_spaces treats
markers among the final controls as part of them.
Results: every case I cut down now typesets like its written-out form.
I compared old and new on 1690 documents (the manual, your papers and
presentations from texmacs.org, other public documents, my own papers):
- 460 documents move, mostly by less than half a point;
- 5 change page count (among them witness.tm and the Pure plugin
manual), each time through a script that now sits where the
written-out markup puts it, and the page breaks that follow from it.
3. TWO OTHER BUGS I FOUND ON THE WAY
- Format leak: format_width_rep, format_cell_rep, format_vstream_rep and
query_vstream_width_rep set ref_count= 1 in their constructors, and
make_format_* then wraps them in a handle that counts them again. They
were never freed, together with their line items. This hit every table
cell with hyphenation, including numbered section titles through
prefixed-line.
- Table width: lazy_table_rep::produce read table-width without exec,
while format_table does exec it.
4. THE REWRITER
I followed your notes ("Upcoming style rewriting tool", "Increased
laziness"):
- Partial evaluation: the rewriter evaluates the document with residuals
for whatever depends on the typesetter (lengths in units, box-info,
labels, counters seen by the typesetter).
- Input keys: the memorizers record what they read.
- Typesetter on the rewritten tree: with TEXMACS_STYLE_TYPESET=1 the
editor typesets the rewritten tree. The boxes keep the document's
places, so the cursor and typing work.
- Incremental edits: after an edit, the rewritten tree is diffed and
given to the typesetter as patches. A keystroke now costs the same as
in the normal editor.
- Results:
* all 696 English documentation pages print identically to the
normal typesetter;
* about 90 of 1000 corpus documents still differ, for reasons I
mostly understand (see the questions below).
The design and every decision I took are in src/docs/pure-style.md and
src/docs/pure-style-decisions.md on the branch.
5. QUESTIONS
1. Did you mean the markers to have extents (the cmr x-height)? For
instance, to give empty macro lines a height, or to keep the cursor
visible? Is there a reason they should affect layout that I am
missing?
2. Is it right that a marker can never be a script's base? Or did you
intend scripts to attach to the boundary of a macro?
3. Was italic_restore meant to query the corrections again?
4. Argument markers in the rewritten tree: after the rewriter
substitutes the arguments, the typesetter no longer knows where an
argument began and ended, so the cursor boundaries of arguments are
lost. I tried to recover them in the typesetter, and it made things
worse. I think the rewriter should mark substitutions itself. How did
you plan it?
5. Side effects in residual branches: for-each and counter resets inside
undefined macros (footnotes) are not visible to the typesetter. Did
you foresee state in the rewriter beyond assignments?
6. Some differences remain that I cannot explain. One is in your Beff
and lagrange notations, specific to the rewriter and not caused by
markers. I would love your opinion.
If you have time, a look at the branch would help me a lot: even only
the rewriter's design notes and the marker changes in concat_boxes.cpp,
concater.cpp, concat_post.cpp and lazy_paragraph.cpp. The branch is
https://github.com/mgubi/texmacs/tree/wip_pure_style. The marker fixes
for the normal typesetter alone are in
https://github.com/mgubi/texmacs/pull/448.
Best,
Max
_______________________________________________
Texmacs-dev mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/texmacs-dev