bug-groff
[Top][All Lists]
Advanced

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

[bug #61423] [libgroff] allow paths in "name" directive of font descript


From: G. Branden Robinson
Subject: [bug #61423] [libgroff] allow paths in "name" directive of font description file, restoring historical groff behavior
Date: Sun, 7 Nov 2021 02:20:18 -0500 (EST)
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0

Follow-up Comment #9, bug #61423 (project groff):

This ticket appears to have turned over a very old rock with some very ugly
creatures living beneath it.

It appears that the argument to the `name` directive isn't necessarily a file
name.

It's an "external name".  Both CSTR #54 and existing _groff_ documentation are
pretty vague about what that _means_.

CSTR #54, on the `fp` request:

> This is a statement that a font named _F_ is associated with position _N_.
It is a fatal error if _F_ is not known. For fonts with names longer than two
characters, _L_ refers to the long name, and _F_ becomes a synonym.

(I note as an aside that _groff_ does not treat the foregoing failure mode as
a _fatal_ error, nor in my opinion should it.)

Regarding the font description file itself, CSTR #54 is hopelessly circular.

> name _str_ <tab> name of font is _str_

Wow, thanks.

_groff_'s own Texinfo manual says this:


The 'fp' request has an optional third argument.  This argument
gives the external name of the font, which is used for finding the
font description file.  The second argument gives the internal name
of the font, which is used to refer to the font in 'gtroff' after
it has been mounted.  If there is no third argument then the
internal name is used as the external name.  This feature makes it
possible to use fonts with long names in compatibility mode.


If the above were completely true, then there would be no reason for font
description files to have an `internalname` directive; a font's internal name
would be completely document-dependent.

Indeed, I can say:


.fp 5 Normal R
.fp 6 Slanted I
.fp 7 Heavy B
.fp 8 Emphatic BI
.ft Normal
Hello, Joe.
What
.ft Slanted
do
.ft Heavy
you
.ft Emphatic
know?


And it works as you would expect in groff 1.22.4 and Git HEAD.  (Hooray,
something I didn't regress.)

But if a font's internal name is document-dependent, what are we to make of
`internalname` as used (only) by grodvi, grops, and grotty?

It seems like we're using the highly specific jargon "internal[ ]name" to mean
two completely different things.  One is a within-document alias for a font
name (or for a font mounting position, for that matter, which is what a font
name already is); the other is a driver-specific tag used only for
communications between _groff_ objects of the class `font` and the output
drivers.

I note that the member function `font::get_internal_name`, which refers _only_
to this latter concept, has _no_ call sites outside of specific output
drivers.


$ git grep get_internal_name
src/devices/grodvi/dvi.cpp:  const char *nm = f->get_internal_name();
src/devices/grops/ps.cpp:     .put_literal_symbol(f->get_internal_name())
src/devices/grops/ps.cpp:  const char *psname = sty.f->get_internal_name();
src/devices/grops/ps.cpp:    rm.need_font(psf->get_internal_name());
src/devices/grops/ps.cpp:      
.put_literal_symbol(tem->p->get_internal_name())
src/devices/grotty/tty.cpp:  const char *num = f->get_internal_name();
src/include/font.h:  const char *get_internal_name();   // Return the
'internalname'
src/include/font.h:                     // a null pointer.  Used by
get_internal_name().
src/libs/libgroff/font.cpp:const char *font::get_internal_name()


This member function accesses a member variable called `internalname`.  *These
member names are very confusing*.  They have to do _only_ with the
device-specific internal name.  The `internalname` member variable is never
read by any code elsewhere in libgroff; its accessor member function is called
_only_ by output drivers.  For grodvi, it's supposed to refer to the name of
the corresponding TFM file.  For grotty, it's a bit mask, for Christ's sake.

I think we have a choice ahead of us:

1. Validate the font description file's `name` directive upon attempted load
against the "internal name" (note the space), the mandatory 2nd argument to
`fp`.  If we do this, slashes are indeed prohibited.  it will also serve to
verify that this internal name is obviously related to the name of the font
description file on the file system.

This "internal name" (mind the gap) is what is referred to as `name` in the
`font` class, and it is what is ultimately passed to `font::open_file` in
fontfile.cpp
<https://git.savannah.gnu.org/cgit/groff.git/tree/src/libs/libgroff/fontfile.cpp#n61>.

(One might reasonably ask why this `name` (really, `nm`) is being passed to
`open_file` when `name` is a member variable of an object of the very class
whose member function this is.  Why do we pass it when we should already know
it?  The answer is that an object of class `font` is not completely
initialized until the font description file has been read, and that hasn't
happened yet before the file has been opened.  In fact, there's a lot of
validation that has to happen before a font object can be assumed valid.  It
is my recent addition of more such validation that prompted Dave to file this
ticket.)

But maybe no one actually needs validation of this sort.  If they `cp A B`
inside a font directory, maybe we shouldn't stop them from loading the font
description file `B` without changes.

2. Another possibility is to validate the value of the `name` directive
against the external name supplied to the `fp` request.  Since that external
name is an optional argument, the validation would only be performed if it
were present.  Assuming that a disciplined name space grew up around external
font names in the groff ecosystem, documents and macro packages could then use
the `fp` request to ensure that they're getting exactly the fonts they wanted.
 (A discipline of syncing this external name and `name` directive contents
with _actual_ font files, like version x.y.z of font FooBar from Foundry
BigCorp, is a necessary but independent prerequisite for this benefit to be
realized.)

One of the things TeX touts about itself is its core principle of never
regressing the renderability of anything.  Knuth and his descendants took this
principle so seriously that they leveraged the file system as a registry and
wrote filename invariance into their software licenses, eventually leading to
tension
<https://www.researchgate.net/publication/236552996_Reflections_on_the_history_of_the_LaTeX_Project_Public_License_LPPL_---_A_software_license_for_LaTeX_and_more>
with the Free Software movement's equally deep dedication to the principles of
modularity and interchangeability.

The file system was used as a registry because it was guaranteed to be there
(in a rare move, Knuth kept his yak-shaving clippers
<https://yakshav.es/the-patron-saint-of-yakshaves/> in his pocket).  I
disagree with that choice but sympathize with the motives behind it.  _groff_
could do worse than to offer one, for fonts, via this mechanism.  For an
example of how _not_ to do a font registry in a way that humans want to deal
with, see X (Window System) logical font descriptions
<https://en.wikipedia.org/wiki/X_logical_font_description>.

I think option #2 would be more in line with what Dave was already doing.

Another independent but important issue in my view is to deprecate that
driver-specific `internalname` member variable as soon as possible in favor of
some other name.  The design of the font description file format suggests that
a driver could pick any usefully descriptive name it wanted, however I don't
think libgroff offers the font description as a general key/value store.  This
`FONT_COMMAND_HANDLER` business
<https://git.savannah.gnu.org/cgit/groff.git/tree/src/libs/libgroff/font.cpp#n1283>
appears to be the correct the mechanism, so that output drivers would extend
the class and supply their own member functions, and grodvi, grolbp, grolj4,
and grops all seem to have done so for other directive names.  But this wasn't
done for `internalname`.  For some reason, the `internalname` member variable
became an ersatz union--in other words, a junk box.

In the short term I propose to rename the `internalname` and
`get_internal_name` members of `font` to something else--almost _anything
else_, even arrant nonsense, like "mxyzptlk", would be an improvement because
at least then it would be impossible to infer identity with the other, much
higher-profile, thing groff calls an "internal name".

For compatibility with old font files, recognition of the `internalname`
directive name would have to be retained.  But we can use the new name going
forward.  Right now I don't have a better idea for a new name than
"disambiguator" or "classifier", which are pretty weak...I challenge the
reader to come up with a term that can encompass grodvi, grops, and grotty's
usages (TFM file name, PostScript font name, bit mask).

In the longer term, I guess the `FONT_COMMAND_HANDLER` thing should actually
be exercised on the output driver side of things as seems to have been
originally intended.  Then the `font` class wouldn't need the
`get_internal_name` member function at all.

A lot of this comment will need to be copied to a Savannah ticket, but I
wanted to get this down while the result of my investigations was fresh in my
head.

The scope of _this_ ticket remains deciding between the 2 options above in
`fp` request handling.

Whew.  I think I'm going to pour myself a drink.

    _______________________________________________________

Reply to this item at:

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

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




reply via email to

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