Follow-up Comment #11, bug #68671 (group groff):

[comment #7 comment #7:]
> Hi Deri,
> 
> [comment #4 comment #4:]
>> On Thursday, 3 September 2026 04:07:01 British Summer Time you wrote:
>>> Follow-up Comment #1, bug #68671 (group groff):
>>> [comment #0 original submission:]
>>> 
>>>> The issue is that groff has 2 ways of setting the line width:-
>>>> 
>>>> Mode 1 (the original - used by tbl if you include linesize(n)) is to make
>>>> lines proportional to the current font size.
>>> 
>>> This is a dusty corner for me, but as I understand it, that is supposed to
>>> be what a negative line thickness means.  This quantity is not tracked in
>>> the formatter _except_ as a drawing command parameter.
>> 
>> Not quite. Tbl's linesize outputs a '\s[nn]...draw...\s0' each time it wants
>> 
>> to draw a line. The 'nn' is controlled by 'linesize'.
> 
> I don't think you've overturned my claims.

What do you think the \s pair is for - if not to affect the line width drawn
by the output driver - but this only works if the output driver is in mode 1 -
as I have tried to elucidate for you in earlier replies. The original pdf
comparing grops/gropdf line drawing clearly shows that once \D't 4000' is
given all the \s changes stop working until a \D't -1' switches the driver
back to mode 1.

> The formatter, GNU _troff_, *does not track* the line thickness as a
> parameter of any object it manages--not in an environment nor anything else.

But the output drivers do!

> You're right that GNU _tbl_ does manipulate the type size as you describe,
> bracketing drawing commands that draw the rules of a table.
> 
> However, those type size manipulations are useless, ineffectual.  Observe.
> 

> $ cat ATTIC/thicc-table-rules.roff
> .sp 1i
> \D't 2400'
> .TS
> allbox tab(@);
> L L.
> foo@bar
> baz@qux
> .TE


You have switched the output driver to mode 2 before the table, tbl doesn't
know that so it continues to try to effect linewidth by changing font size.
There is a big disadvantage in taking away tbl's ability to affect linewidth
by switching to mode 2, tbl alters cell sizes to take into account current
linesize() but it can't if mode 2 is in effect. This can be seen in
tbl-dance.png.

> Your claim about how _tbl_ constructs input for _troff_ is correct...
> 

> $ tbl ATTIC/thicc-table-rules.roff | grep D
> \D't 2400'
> \h'|\n[3cd0]u'\D'l |\n[3cd2]u 0'\c
> \v'.25m'\h'\n[3cd2]u'\s[\n[3lps]]\D'l 0 |\n[3rt0]u-1v'\s0
> \v'.25m'\h'\n[3cd0]u'\s[\n[3lps]]\D'l 0 |\n[3rt0]u-1v'\s0
> \v'.25m'\h'\n[3cd1]u'\s[\n[3lps]]\D'l 0 |\n[3rt0]u-1v'\s0
> \h'|\n[3cd0]u'\D'l |\n[3cd2]u 0'\c
> .if n \Z@\r\D'l 0 2v'@\c
> \h'|\n[3cd0]u'\D'l |\n[3cd2]u 0'\c
> .if n \Z@\r\D'l 0 2v'@\c


> 
> ...but the technique is ineffectual, as _I_ claim.  See attached PostScript
> and raster image made therefrom.

It definitely _is_ effectual, so long as you don't use \D't nnnn' before the
table. 

> $ groff -t ATTIC/thicc-table-rules.roff > ATTIC/thicc-table-rules.ps
> $ okular ATTIC/thicc-table-rules.ps


> 
> Thus, I suspect we have an opportunity here to (slightly) simplify GNU
> _tbl_'s rather frightening-looking output.

I don't think so, currently it works as intended.

>> So it is assuming the output driver is in mode 1 (width controlled by font
>> size).
> 
> Given the foregoing, I believe GNU _tbl_'s assumptions in this area are
> incoherent.

How so? I definitely understand, so it can't be totally incoherent.

>> You can't have a negative font size.
> 
> Strongly agreed.  It's an old, bad habit of C programmers to use invalid
> and/or conceptually incoherent notions as vehicles for in-band smuggling of
> auxiliary information.
> 
>> You can have a negative \D'-1' line thickness, which has 
>> the special meaning for the output driver
> 
> Agreed.
> 
>> to now use mode 1.
> 
> I'm strongly reluctant to adopt your nomenclature for our documentation, but
> if it helps us to communicate in Savannah tickets, it's not bad.
> 
> Don't count on me to correctly recall the meanings of "1" and "2", though.  I
> can never keep "Type I" and "Type II" errors straight in statistical
> hypothesis testing, either.

Let me help you. Mode 1: the first method "invented"  chronologically, the
primary method available when troff starts, useful for pre-processors - makes
sense when typesetting equations, tables, for stroked lines to be proportional
to font size. Mode 2: the second method "invented" chronologically, not the
primary method used on startup - useful when a specific width is required for
a line and avoids a computation of what font size to set before drawing the
line to achieve a precise thickness.

I hope this helps.
 
> https://en.wikipedia.org/wiki/Type_I_and_type_II_errors
> 
>> This is code from grops:-

>> void ps_printer::set_line_thickness_and_color(const environment *env)
>> {
>> if (line_thickness < 0) {
>> if (output_draw_point_size != env->size) {
>> // we ought to check for overflow here
>> int lw = ((font::res / (72 * font::sizescale))
>> * linewidth
>> * env->size)
>> / 1000;
>> out.put_fix_number(lw)
>> .put_symbol("LW");
>> output_draw_point_size = env->size;
>> output_line_thickness = -1;
>> }
>> }
>> else {
>> if (output_line_thickness != line_thickness) {
>> out.put_fix_number(line_thickness)
>> .put_symbol("LW");
>> output_line_thickness = line_thickness;
>> output_draw_point_size = -1;
>> }
>> }


> 
> Yup.  That looks consistent with our shared understanding.
> 
>> line_thickness:              Set by 'Dt' (Default -1)
>> output_line_thickness:       Current mode 2 thickness
>> env->size:           Set by 'snnnn'
>> output_draw_pointsize:       Current mode 1 thickness
> 
> I would not conceptually organize the parameters in this way.

Nor would I.
 
>> In each mode, the others 'output_' var is set to -1, so that if mode changes
>> a 
>> new postscript LW command is certain.
> 
> Today I learned of the PostScript `LW` command...
> 

That means, if you spot two lines you think have different widths you can look
for the 'nn LW' command in effect before the lines are drawn, in the age of
AI, don't trust your eyeballs.

>>> I don't think GNU _troff_ has any notion of "mode 1" or "mode 2".
>> 
>> It is to save bloody typing "proportional to current type size" (M1) or "set
>> 
>> by \D't'" (M2), all over the place. I hope you don't mind.
> 
> I don't, but please keep the caveats above in mind.  Caveman developer prone
> to swap "1" and "2".
> 
Hopefully my suggestion above, for remembering them, can help. Ugg.
 
>> troff knows values set by \D't' and \s but it does not care what the output
>> 
>> drivers do with them, although current horizontal position is tracked but I
>> 
>> don't think it takes into account width of stroked vertical lines. 

>> printf "\D't 0'\n.sp 1i\nHullo\\\v'-.5c'\D'l 0 1c'\\\v'-.5c'World\n\D't 
>> 6000'\n.sp 2\nHullo\\\v'-.5c'\D'l 0 1c'\\\v'-.5c'World\n"|test-groff -Tpdf|
>> okular -


>> 
>> This shows the linewidth is not taken into account by troff when tracking 
>> horizontal position.
> 
> I think you're right, and this is another point that I don't think we
> document, but could and should.

Maybe, my model of how it works is there is a text space and a drawing space
with very little interaction between them. Groff has some esoteric rules about
where the current 'cursor' is after a draw command and that is about it. If
circ.e is the right most pixel of a circle then if you draw a filled circ the
cursor is left at circ.e but if you stroke a circ thw cursor is left 1/2
linewidth west of circ.e.

>>> I think what you are observing is the product of a few interacting
>>> phenomena:
>> 
>> What I am observing, is a difference in which mode is the default start up 
>> mode grops v.  gropdf. Nothing at all to do with troff!
> 
> Mostly agree, except approximately zero people on Earth write raw trout or
> grout, but instead they use _troff_ (perhaps via a preprocessor) to
> manipulate these parameters, so greater clarity about how such manipulations
> take place is desirable.

It is clear to me from the documentation you quoted, it could be improved.
 
>>> 1.  The formatter doesn't even _have_ a "line thickness" property; this is
>>> a
>>> property of some (not all) output drivers, exposed only via the 't'
>>> drawing
>>> command.
>>> [https://cgit.git.savannah.gnu.org/cgit/groff.git/tree/src/roff/troff/input.
>>> cpp?h=1.24.1#n10406 You can see here that GNU _troff_ has no special logic
>>> to interpret a 't' drawing
>>> command]--[https://cgit.git.savannah.gnu.org/cgit/groff.git/tree/src/roff/tr
>>> off/input.cpp?h=1.24.1#n10523 the formatter blindly passes it to the
>>> output
>>> device, the same as any extension.]  
>>> And `t` **is** in fact an extension;
>>> CSTR #54 makes no mention of it (screenshot attached).
>> 
>> Which is why I wrote (above) "Mode 2 (a groff extension)".
>> 
>>> I perceive a possible documentation gap here; I suspect that the man page
>>> of
>>> every output driver that implements the `t` drawing extension command
>>> should document its semantics, and those semantics should be as described
>>> above for internal consistency.
>> 
>> If the current output drivers which stroke lines all do the same thing the 
>> current documentationb is adequate.
> 
> Well, they didn't all do the same thing until yesterday. :)

:-)

> And for that matter, we haven't tested our other _troff_-mode devices,
> _grodvi_, _grolbp_, and _grolj4_.  Anyone can test the first with _xdvi_(1).
> I can test the last with my Brother laser printer, and the one in the
> middle...only God knows.
> 
>>> 2.  GNU _tbl_ does not bother to configure a line thickness unless the
>>> user
>>> specifies the `linesize()` region option.
>>> 
>>> _tbl_(1):
>>> 
>>> linesize(n)      Draw lines or rules (e.g., from box) with a
>>> thickness of n points.  The default is the current
>>> type size when the region begins.  This option has
>>> no effect on terminal devices.
Here's your answer. Without a linesize() the width is taken from the current
font size (assuming output driver is in mode 1). The final example in
tbl-dance is an example of this - mode 1, no linesize(), but previous text
before the table set in 25pt - lines are as if linesize(25) used but text in
table is 25pt as well.

>>> 
>>> There may be a problem here.  The default isn't in fact the
>>> **formatter**'s
>>> default (what is described here), but the formatter's **current state**. 
>>> Even more precisely, it's the **output driver**'s current state, which, if
>>> it supports the `t` drawing extension command at all, we expect it to
>>> absorb and interpret as we document.

tbl was written before mode 2 was invented so of course its talking
(correctly) about mode 1.
 
>>> As evidence, here's a simple boxed table as prepared by GNU _tbl_, with
>>> all
>>> the drawing commands filtered:
>>> 

>>> $ printf '.sp 1i\n.TS\nbox;\nL.\nfoo\n.TE\n' | tbl | grep D
>>> \h'|\n[3cd0]u'\D'l |\n[3cd1]u 0'\c
>>> \v'.25m'\h'\n[3cd1]u'\s[\n[3lps]]\D'l 0 |\n[3rt0]u-1v'\s0
>>> \v'.25m'\h'\n[3cd0]u'\s[\n[3lps]]\D'l 0 |\n[3rt0]u-1v'\s0
>>> \h'|\n[3cd0]u'\D'l |\n[3cd1]u 0'\c


>>> 
>>> Not a `\D't'` in sight.
>> 
>> Yes, it is assuming the output driver is in Mode 1 (notice the
>> \s[\n[31ps]]/
>> \s0 pairs around the \D'l' commands).
> 
> A red herring, I submit.

Yes, I am expecting your submission on this point, it is not even a pinkish
herring, it is the way tbl controlled line widths before mode 2 was
introduced.

>> From this I would expect \n[31ps] is calculated from 'linesize'.
> 
> I expect you're right, but it turns out to have no effect on the output.

Look again at the first pdf I uploaded (comparing grops/gropdf) the lines
which start 'snn:' are set with a .ps nn before the line is drawn, and lines
starting 'tnnnn:' have a \D't nnnn' before the line is drawn. It will look
better if you 200% zoom. You can clearly see the .ps affecting the width
_until_ we start using \D't' then the .ps changes have no effect (stuck on
\D't 4000') until \D't -1' is issued and we are back to mode 1.

>>> If the user throws down a `\D't 24'` right before a `.TS`, and does not
>>> use
>>> the `linesize()` region option, any rules in the ensuing table gonna be
>>> thicc.
>> 
>> Partially correct, I think you mean \D't 2400' (millipoints),
> 
> Yes!  Thank you.
> 
>> and, particularly, 'linesize' is completely ignored if you use it.
> 
> I disagree!  Another exhibit.
> 

> $ cat ATTIC/thicc-table-rules2.roff
> .sp 1i
> \D't 2400'
> .TS
> allbox linesize(10) tab(@);
> L L.
> FOO@BAR
> BAZ@QUX
> .TE
> $ tbl ATTIC/thicc-table-rules2.roff | grep D
> \D't 2400'
> \h'|\n[3cd0]u'\D'l |\n[3cd2]u 0'\c
> \v'.25m'\h'\n[3cd2]u'\s[\n[3lps]]\D'l 0 |\n[3rt0]u-1v'\s0
> \v'.25m'\h'\n[3cd0]u'\s[\n[3lps]]\D'l 0 |\n[3rt0]u-1v'\s0
> \v'.25m'\h'\n[3cd1]u'\s[\n[3lps]]\D'l 0 |\n[3rt0]u-1v'\s0
> \h'|\n[3cd0]u'\D'l |\n[3cd2]u 0'\c
> .if n \Z@\r\D'l 0 2v'@\c
> \h'|\n[3cd0]u'\D'l |\n[3cd2]u 0'\c
> .if n \Z@\r\D'l 0 2v'@\c
> $ groff -t ATTIC/thicc-table-rules2.roff > ATTIC/thicc-table-rules2.ps
> $ okular ATTIC/thicc-table-rules2.ps

All you are proving here is that if you use a \D't nnnn' before a table all
lines will be that thickness because you have switched to mode 2. And we knew
that already!!

> Make a prediction of what the output will look like before inspecting my
> attachments!

Err, would it be all lines are exactly 2.4pt wide?
 
>>> I tentatively conclude that GNU _tbl_'s implementation is correct and the
>>> documentation wrong.  But we could change tbl to save the configured line
>>> thickness when entering the table region, explicitly set it (to '-1' if
>>> not
>>> user-specified), and then restore the saved line thickness when exiting
>>> the
>>> table region.
>> 
>> The documentation for tbl could be improved by saying that linesize only
>> works 
>> if you have not used \D't' anywhere before the table
> 
> Ah, you anticipated my rebuttal, at least in part.
> 
>> and mention that issueing \D't -1' before the table will restore linesize
>> working.
> 
> I'd feel lame offering that advice to users.  I think it would be better to
> treat the line thickness as we treat other parameters of the environment;
> save the configuration on the way into the table region, operate with clear
> semantics within it (which are already documented); and restore the saved
> parameters on the way out.
> 
>>> 3.  Judging by your file #58940 LineThk-examples2.pdf exhibit, it appears
>>> to
>>> me that the vinculum in an _eqn_ fraction is thicker when the equation is
>>> set inside a _pic_ box than when the equation is not thus wrapped.  That
>>> seems inconsistent, and potentially a bug (or a "NEWS"-worthy feature
>>> change if we alter it).
>> 
>> Is the "vinculum" the  fraction line?
> 
> Yup.
> 
>> If so they are the same width in both 
>> formulas.
> 
> I'll have to look more closely, then, or employ a more sensitive instrument
> than my crude eyeballs.

Or look at the LW commands in the postscript. 

>> What is "odd" is the tail of the first arrow is thicker than the 
>> second arrow, that is, until you realise that the font size at the start of
>> 
>> the picture (10.95: PICTURE) is different to the fontsize used in the
>> equation 
>> (10: H(ω)) so the proportional line thickness would change.
> 
> Hmm.  This might be a bug.
> 
>>> 4.  GNU _pic_ steps on the line thickness, explicitly setting it to '-1'.
>>> Like GNU _tbl_, it performs no save/restore dance.
>>> 
>> 
>> It lookks like (something) already does that:-
>> 

>> printf '.PS\ncircle "dig here";\n.PE' | pic | test-groff -Z
>> x T ps
>> x res 72000 1 1
>> x init
>> p1
>> DFd
>> V12000
>> H108000
>> n12000 0
>> md
>> V12000
>> H72000
>> s10000
>> Dt -1000 0   <----
>> h1000
>> n12000 0
>> V30000
>> H72000
>> Dc 36000
>> n12000 0
>> x font 5 TR
>> f5
>> V32200
>> H73755
>> tdig
>> wh2500
>> there
>> n12000 0
>> x trailer
>> V792000
>> x stop


> 
> I see no saving and restoring here, just a single configuration of the line
> thickness parameter.

Yes, pic always uses mode 2 to set line thicknesses, but it exits changing to
mode 1 (even if, before the picture started, it was  in mode 2).

> Possibly GNU _pic_ should also do what I have proposed here for GNU _tbl_.
> 
> Here's another thought experiment.  What should the output of the following
> look like?
> 

> $ cat ATTIC/thicc-pic.roff
> .sp 1i
> Check out my \D't 2400'\D'l 1i 0' thick line!

* Now in mode 2, 2.4pt line drawn.

> .PS
> circle "dig here";
> arrow right;
> circle "no, here";

* no "thick" attribute and "linethick" default -1, so thin lines (.1pt) 

> .PE

* pic exits, setting to mode 1

> Is \D'l 1i 0' this line as thick?

* Of course not, pic put you back to mode 1 when it exited (see above), the
2.4pt thickness is your mode 2 thickness. If you want 2.4pt in mode 1 wrap the
second \D'l' in \s[60]...\s0. (Check the LWs).

> $ groff -p ATTIC/thicc-pic.roff >| ATTIC/thicc-pic.ps
> $ okular ATTIC/thicc-pic.ps


> 
> Here's a partial spoiler.
> 
I think I got it right. I'm sorry you are having difficulty getting your head
around all this, I am trying.

> $ pic ATTIC/thicc-pic.roff | grep "D't"
> Check out my \D't 2400'\D'l 1i 0' thick line!
> \D't -1.000p'\h'1.000p'
> \D't 0.100p'\h'-0.100p'
> \D't -1.000p'\h'1.000p'


> 
> On a completely different note:
> 
> I note that after your commit, the test script
> _src/roff/groff/tests/pdf-device-smoke-test.sh_ is failing.  It seems to be a
> spurious failure.  I likely need to "loosen" the regexes I'm using, and
> possibly take _od_(1) out of the test procedure altogether.

Something like this:-

printf ".nf\n.kern 0\nHello my big beautiful World"|test-groff -Tpdf -P-f3 |
grep -Faq '0.000 Tw [ (Hello my big beautiful World)] TJ'; echo $?

zero is a match.

> Maybe I should be testing only production of plausible "grout" for the "pdf"
> device; anything about actual PDF file content could shift to test scripts
> under _src/devices/gropdf/tests_.

Up to you.
 
> Regards,
> Branden

Cheers

Deri


(file #58952, file #58953)

    _______________________________________________________

Additional Item Attachment:

Name: tbl-dance.png                  Size: 34KiB
    <https://file.savannah.gnu.org/file/tbl-dance.png?file_id=58952>

Name: tbl-dance.trf                  Size: 552B
    <https://file.savannah.gnu.org/file/tbl-dance.trf?file_id=58953>


    AGPL NOTICE

These attachments are served by Savane. You can download the corresponding
source code of Savane at
https://savannah.gnu.org/source/savane-8693ef25c3bda93e45bf8920c42c31d599d37348.tar.gz


    _______________________________________________________

Reply to this item at:

  <https://savannah.gnu.org/bugs/?68671>

_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/

Attachment: signature.asc
Description: PGP signature

Reply via email to