1
0
mirror of synced 2026-01-13 07:29:52 +00:00
Interlisp.medley/docs/internal/FONTCODECHANGES.tedit
rmkaplan 097f346c3b
Rmk143 INITVARS command for MEDLEY-INIT-VARS, FLUSHFONTCACHE (#2383)
* loadup scripts:  set MEDLEY-INIT-VARS to NOBIND before loading MEDLEYDIR
so that INITVARS in MEDLEYDIR replaces any previous settings in the loadup-sysout

* FONT:  add cache for FONTSAVAILABLE, add FLUSHFONTCACHE.  See FONTCODECHANGES.tedit

* Make FONTEXISTS and FONTSAVAILABLE consistent
2025-11-30 09:14:22 -08:00

162 lines
34 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Medley FONT CODE CHANGES
2
4
1
FONT CODE CHANGES
1
4
By: Ron Kaplan
This document last edited on August 29, 2025.
Introduction
This document describes changes made to the font implementation in order to simplify the code, remove some unecessary (and sometimes broken) features, and to generalize some of the interfaces. The new code also allows the chain of font coercions to fill in not just entirely missing character sets but missing characters in character sets that are only partially populated.
Font data structures
The legacy fields FBBOX FBOY BBDX BBDY \SFLKerns \SFRWidths of FONTDESCRIPTOR have been removed and new fields have been added:
FONTCOMPLETEP: T if all character sets of the font are ©©char-complete¹¹ as defined below. In that case, all coercions are suppressed and the value is used by generic \BUILDSLUGCSINFO when a font's getcharset function returns NIL.
FONTHASLEFTKERNS: T if at least one character set has left-kern information (althoughthe interpretation of kerning information is still not well defined).
FONTSLUGWIDTH: The width of the slug/replacement character in the font, in font-scale units.
FONTTOMCCSFN: If not NIL, a function that translates character codes from the font's encoding to MCCS (e.g. SYMBOLTOMCODE). A hardcopy device can apply its own MCCS-to- device encoding function to the result (e.g. MTOUCODE, MTOXCODE).
FONTCHARENCODING: The char-encoding of (presumably for charset 0) of the font (e.g. SYMBOL, ALTOTEXT).
Element 256 (=the constant SLUGCHARSET) of the FONTCHARSETVECTOR has been reserved for a slug CHARSETINFO with a slug (black box or equivalent whose width is FONTSLUGWIDTH) entry for every character. A pointer to that single slug CHARSETINFO is installed in the vector for a character set that is requested but for which it is known that it will never have real characters. Thus, an element of the vector is NIL if a request for such a charset has not yet been made and will be the font's single slug-charsetinfo after the first request.
New fields have been added to the CHARSETINFO datatype:
CSSLUGP: This flag is T for all slug charsetinfos to say that the charset does not exist in the font. If FONTCOMPLETEP is not NIL, there may be an attempt to coerce from another font or charset.
CSCOMPLETEP: T if the CHARSETINFO is char-complete (a slug charsetinfo is always char-complete). Suppresses further attempts to fill in individual characters from other fonts.
CHARSETNO is set to the character-set number of this charsetinfo when it is installed in its font.
CSINFOPROPS holds an alist of device-independent or device-specific properties that may be associated with a charset. Properties can be set or retrieved by the function CHARSETPROP.
(CHARSETPROP CSINFO PROP NEWVALUE) [Macro]
CSINFO is a CHARSETINFO. If NEWVALUE is provided, it is stored as the new PROP value of CSINFO, and NEWVALUE is returned. Otherwise, the current PROP value of CSINFO is returned.
Font creation
The CHARSET argument to FONTCREATE can be a character-set name, or an octal or hex number string, not only a character-set number. Thus (FONTCREATE '(Gacha 10 NIL NIL NIL Greek) is another way of insuring that character set 46Q is instantiated. (A new function CHARSET.DECODE has been added to LLREAD).
FONTCREATE has been factored into two subfunctions, \FONT.CHECKARGS and FONTCREATE1. \FONT.CHECKARGS interprets the flexible ways in which the properties of the desired font can be expressed and/or defaulted, and checks them for validity. FONTCREATE1 finds or creates the font, knowing that the arguments have been standardized and validated.
(\FONT.CHECKARGS FAMILY SIZE FACE ROTATION DEVICE CHARSET ALWAYSFONTSPEC) [Function]
The arguments are examined and possibly coerced or defaulted to values that would be sensible specifications for a requested font. Thus, FAMILY can be
An atomic family name: TIMESROMANÿÿ
ÿ A FONTSPEC, a list of font parameters as defined belowÿÿ
ÿ A fontdescriptor or font class from which the desired properties can be extracted.
SIZE must reduce to a postive integer, FACE must be convertible to a (weight slope expansion) list with (MEDIUM REGULAR REGULAR) as the default. DEVICE defaults to DISPLAY and CHARSET can be a character set name or number; NIL defaults to 0.
If FAMILY specifies a font descriptor that is not modified by any of the other arguments and ALWAYSFONTSPEC is NIL, that font descriptor is returned. Otherwise \FONT.CHECKARGS returns an instance of the FONTSPEC record with coerced/validated (family size face rotation device) values. The caller can use the macro SPREADFONTSPEC to extract the values from that list and set them to its own bindings of FAMILY SIZE etc.
\FONT.CHECKARGS causes an error if any of the arguments is not of the correct type (e.g. FAMILY does not map to an atom, FACE is not a face, etc).
\FONT.CHECKARGS is called by FONTCREATE, but also by other functions that interpret font specifications. (Note: break or trace \FONT.CHECKARGS with caution.)
(\CHARSET.CHECK CHARSET) [Function]
Coerces CHARSET (a number or character-set name) to a valid character set number, mapping NIL to 0. Error if the CHARSET cannot be coerced.
(RECORD FONTSPEC (FSFAMILY FSSIZE FSFACE FSROTATION FSDEVICE) [Record]
An abstraction for the information returned by \FONT.CHECKARGS, FONTSAVAILABLE, and COERCEFONTSPEC and for the argument that is passed through many internal functions. The creation and field-access methods of this record replace systematically the collection of list construction and access methods in previous code.
(SPREADFONTSPEC FONTSPEC ) [Macro]
FONTSPEC is an instance of FONTSPEC. Its values are extracted and set to the caller's variables FAMILY SIZE FACE ROTATION DISPLAY. Most of the internal functions now take only a single FONTSPEC argument instead of the family/size/... variables. Typically FONTSPEC's are now created by \FONT.CHECKARGS and only spread out at the lowest levels, for example, when the fields have to be mapped into substrings of a file name.
(FONTCREATE1 FONTSPEC CHARSET) [Function]
Given that the arguments have been validated and coerced, this finds or constructs the corresponding fontdescriptor and ensures that the character set CHARSET is instantiated and character-complete, as defined below. Returns NIL (without error) if the arguments do not select a font with at least one defined character set (usually character set 0).
If FONTCREATE1 returns NIL, FONTCREATE causes the FONT NOT FOUND error unless its NOERRORFLG argument is T. The error will specify the validated arguments as of the FONTCREATE, even if the failure was down some chain of coercions--the error pops to the top.
Note that the error behavior is different than previously implemented. Before, an error would be generated if the requested CHARSET is not defined even though there is information to instantiate at least one other character set in the font. Now it is judged that the font exists but the requested character set may be filled with slugs (black boxes). Asking for FAMILY FOO will cause an error, but asking for GACHA character-set 5 (which is undefined in MCCS) will not. Characters in that character set will display as black boxes.
FONTCREATE1 retrieves a specified fontdescriptor from the \FONTSINCORE cache, and adds to that cache if it creates a new descriptor. This is done by the PUTMULTI and GETMULTI macros of the MULTI-ALIST package. The previous function used for this purpose, \LOOKUPFONTSINCORE, has been removed.
(\READCHARSET FONTSPEC CHARSET) [Function]
This is a new primitive function for creating the CHARSETINFO of a requested character set based on information from some external source, presumably a file. It generalizes the previous \READDISPLAYFONTFILE to multiple file formats for DISPLAY and even for other font devices.
This calls the new function FONTFILES to get an ordered list of candidate files for the specified font-charset, based on standard font-file naming conventions.
For each file, it runs down the elements on a device-specific list of character-set functions provided by (FONTDEVICEPROP FONTDEVICE 'CHARSETFNS) . Each entry on this list is a triple of the form ÿÿ
ÿ (typename predicatefn getcharsetinfofn)ÿÿ
ÿIf the predicatefn applied to a filename is true, then the getcharsetinfofn is applied. If that produces a CHARSETINFO, that is the value returned; otherwise the next triple is considered. For some file types (e.g. STRIKE, AC) the character set is embedded in the filename. The character set is passed as a parameter for formats that can incorporate information about multiple character sets (e.g. Medley font-format files). The font descriptor is also passed to allow overall font properties to be modified by information in the charset file. For example, the font's FONTSLUGWIDTH might be set when the font's first character set is installed.
(predicatefn FILE/STREAM) [CHARSETFNS entry]ÿÿ
ÿ(getcharsetinfofn FILE/STREAM CHARSET FONT [CHARSETFNS entry]
The current CHARSETFNS entries for the DISPLAY font device are:ÿÿ
ÿ ( ( AC ACFONT.FILEP ACFONT.GETCHARSET)ÿÿ
ÿ ( MEDLEYFONT MEDLEYFONT.FILEP MEDLEYFONT.GETCHARSET)ÿÿ
ÿ ( STRIKE STRIKEFONT.FILEP STRIKEFONT.GETCHARSET))ÿÿ
ÿ(ACFONT.FILEP and ACFONT.GETCHARSET are new functions on AFONT. The MEDLEYFONT functions are on MEDLEYFONTFORMAT. STRIKEFONT.FILEP is a new function on FONT and STRIKEFONT.GETCHARSET on FONT is a rename of the previous \READSTRIKEFONTFILE.)
\READCHARSET records the name of the file as the FILE property of the CHARSETINFO and it stores the list of charset parameters (FAMILY SIZE etc.) as the SOURCE property.
It also stores the character encoding of the charset as the value of the CSCHARENCODING property. The character encoding may be included in the CHARSETINFO returned by the getcharsetinfofn (as for MEDLEYFONT files). Otherwise for character sets other than 0 the character encoding defaults to MCCS, and for character set 0 the character encoding is determined from the family. This is XCCS$ for families in the list NSFONTFAMILIES (Classic, Modern...), ALTOTEXTFONT for families in the list ALTOFONTFAMILIES (Timesroman, Helvetica...), and FAMILY itself for other families (Hippo, Math...). As fonts are converted to MCCS, the encoding property will reflect that fact.
\READCHARSET returns NIL if an appropriate CHARSETINFO cannot be found and read.
(FONTFILES FONTSPEC CHARSET DIRLST EXTLST) [Function]
This new function returns a list of the standard-named files that contain information about CHARSET for FONTSPEC. DIRLST and EXTLST are optional lists of the directories and extensions to be searched for. If DIRLST is not provided, then the FONTCOERCIONS property of FONTSPEC's device is used (see FONTDEVICEPROP below). Similarly, EXTLST defaults to the FONTEXTENSIONS property. The initial values of those properties are respectivelyÿÿ
ÿ ( [MEDLEYDIR]/<fonts>medleydisplayfonts [MEDLEYDIR]/fonts/displayfonts )ÿÿ
ÿandÿÿ
ÿ ( MEDLEYDISPLAYFONT DISPLAYFONT STRIKE )ÿÿ
ÿEventually these will be reduced to just the Medley-format directory and extension.
FONTFILES considers as candidates the standard file names that begin with the octal character-set subdirectory and end with the character set (e.g. c357>GACHA10-MIR-C357) and also file names without any charset indication (simply GACHA10-MIR). The latter is appropriate for multi-charset Medley-font formatted files or fonts for devices that do not distribute their charsets into separate subdirectories.
Font existence and availability
(FONTSAVAILABLE FAMILY SIZE FACE ROTATION DEVICE CHECKFILESTOO?() [Modified function)
The resulting list of fontspecs is sorted by the new function SORTFONTSPECS.
(SORTFONTSPECS FONTSPECS) [Function]
Sorts FONTSPECS alphabetically by device, then family, then by smaller sizes, finally by putting regular/default face before others.
(FONTEXISTS? FAMILY SIZE FACE ROTATION DEVICE) [Function]
FAMILY can be a family name, a FONTSPEC, or a font descriptor/class. This new function returns a non-NIL value if a font descriptor with the specified parameters can be retrieved from \FONTSINCORE or can be constructed from the information in a font-file. It records the result of the search in a separate cache, \FONTEXISTS?-CACHE, to avoid future lookups. This is not equivalent to a direct call to FONTSAVAILABLE because this takes into account the possibility of coercing the requested parameters to the parameters of some other font (e.g. Modern 60 "exists" because it coerces to Modern 24).
(FONTEXISTS? FONTSPEC) [IMAGESTREAMTYPES method]
This new component of the IMAGESTREAMTYPES entry for a font device (DISPLAY, POSTSCRIPT, PDF, HTML...) is a function of the usual (pre-validated) font parameters family, size. face, rotation, device as they are wrapped up in FONTSPEC. It returns the non-NIL value that will be stored in the \FONTEXISTS?-CACHE if it would be possible to create the specified font from file or coercion data.
(FONTFILEP FILE DEVICE) [Function]
This returns the typename of an element of (FONTDEVICEPROP DEVICE 'CHARSETFNS) whose predicatefn applied to FILE is non-NIL.
(\SEARCHFONTFILES FONTSPEC) [Modified function]
\SEARCHFONTFILES has been modified so that it takes a single FONTSPEC argument, not a spread of variables, whose FSDEVICE is used to determine the appropriate directory and extension search lists. Some of the device-specific search functions have been removed.
(FLUSHFONTCACHE TYPE FAMILY SIZE FACE ROTATION DEVICE) [Function]
Removes the specified fonts(s) from from the font cache(s) indicated by TYPE. TYPE can be one of :INCORE :EXISTS :AVAILABLE, or a list containing one or more of those; NIL defaults to a list of all three. FAMILY can be a family name, FONTSPEC, or font. The wild-card * may appear for any of the parameters, and all matching fonts for :INCORE and :EXISTS will be flushed. Since the cache for FONTSAVAILABLE records the list of fonts produced for previous queries, the result only for an exact match of an original query are removed if TYPE is :AVAILABLE. If any of FAMILY etc. is NIL, it is interpreted as the wildcard *. Thus (FLUSHFONTCACHE) will empty all of the caches. The value indicates the number of entries of each type that were removed.
(FLUSHFONTINCORE FAMILY SIZE FACE ROTATION DEVICE) [Function]
Defined as (FLUSHFONTCACHE :INCORE FAMILY SIZE FACE ROTATION DEVICE), to be deprecated.
(\BUILDSLUGCSINFO FONT SLUGWIDTH) [Modified function]
This internal function builds the slug charsetinfo for FONT where each element of the widths vector is SLUGWIDTH. If SLUGWIDTH is not provided it is computed as a fraction of FONT's \SFHeight, and the computed value is installed back into FONT. For display fonts, this also constructs and installs the slug bitmap. This is a modification of the previously existing definition.
Character-set coercion and character completion
Previous code implemented several strategies to fill in a requested character set or font when there is no explicit source data to match that request. There is no file for Greek characters in Gacha 10, say, but MISSINGCHARSETDISPLAYFONTCOERCIONS specified that the Greek character set of Terminal 10 may be a good approximation, and if that did not exit, then Modern was the heuristically next best place to look. If there was no source data for an italic or bold face, the previous code searched for characters in another face that could be algorithmically slanted or fattened. And the variable MISSINGDISPLAYFONTCOERCIONS defined how one whole font could be substituted for another, so that a request for Helvetica 2 would best be satisfied entirely from the Helvetica 4 source files and coercions.
The code for implementing these coercions was recursively tangled, to say the least. But the code was also flawed in another way: its coercions applied at the character-set level and not at the level of the glyphs or other information for individual characters. Consider a request for character set 357Q in Terminal 10. That request is immediately satisfied by the file TERMINAL10-MRR-C357.DISPLAYFONT, and on that basis the code would see no need for further coercion. But that particular file only has information about half a dozen characters, the other symbols in c357 will show up as black-box slugs. If that file had not been there, the coercion would have found the file MODERN10-C357.DISPLAYFONT, which instantiates virtually all the symbols in character set 357. In effect, the partial Terminal-specific file blocked the possibility of replacing its slugs with the glyphs for a much larger collection of characters.
The resulting charsetinfo is thus not ©©char-complete¹¹ in the sense that it does not incorporate all the information that is available directly or indirectly for the characters in that set. Similarly, the font descriptor that includes that charsetinfo is also not char-complete: it includes at least one charset that is not char-complete.
There is a new architecture for charset and character coercion. It maintains the same basic strategy of looking first for an appropriate character-set file and failing that, coercing for a character set in a different font. But the best charsetinfo, when it is finally located, is then further processed if it is not already marked as char-complete (its CSCOMPLETEP flag is NIL). The function COMPLETE.CHARSET is called to see if any of the slugs in that charsetinfo can be individually replaced by information from charsets further down in the coercion chain. Note that the MISSINGxxx variables have been removed, and the coercion process is driven by the values returned by the new function FONTDEVICEPROP described below.
(COMPLETE.CHARSET CSINFO FONTSPEC CHARSET FONT COERCIONS ) [Function]
For each code from 0 to \MAXTHINCODE that is instantiated as a slug in CSINFO, COMPLETE.CHARSET searches through the coercions to see if it is not a slug in some later character set. If a non-slug entry exists for that code in CHARSET, its character information is copied up into CSINFO. At the end, CSINFO is marked as char-complete whether or not anything has been changed. But if at least one slug was replaced, the original SOURCE property of CSINFO is changed to reflect the fact that it has now been specialized to the FAMILY SIZE etc. parameters of FONT. (If no replacements are made, the original source is a direct reference to the charset information, skipping over any intermediate coercion steps. )
The slugs in a display character set are detected by the function SLUGCHARP.DISPLAY (this should be generalized to device-independent interface function).
(SLUGCHARP.DISPLAY CODE FONT/CHARSETINFO) [Function]
If the second argument is a font descriptor, CODE is interpreted as a character code in the full range 0 to 65535, and the target character set in that font is extracted with CODE's high-order byte. Otherwise, CODE must be an integer between 0 and 255. The predicate is true if the bitmap for the code in this character set has the same offset as the bitmap of the slug (which is stored at position 256 in every charsetinfo). (It remains to generalize this predicate to POSTSCRIPT, HTML, and other font devices.)
(COMPLETE.FONT FONT EVENIFCOMPLETE) [Function]
Unless FONT is already marked as char-complete (or EVENIFCOMPLETE is T), this function makes sure that there is a charsetinfo for every charset from 0 to 255. If an actual charset can exist directly or by coercion for FONT, the charsetinfo for that charset is instantiated and made char-complete. Slug charsets are introduced for charsets that do not exist. At the end the FONTCOMPLETEP flag is set to T.
The function FONTDEVICEPROP returns coercion and other information for a particular font device:
(FONTDEVICEPROP FONTDEVICE PROP) [Function]
Returns the value of property PROP for FONTDEVICE. The following properties are defined:
FONTCOERCIONS: A list of match/target pairs (see below) to coerce entire fonts on the given device
CHARCOERCIONS: A list of match/target pairs for coercing individual characters and charsets
FONTDIRECTORIES: A list of directories to search for font files on this device
FONTEXTENSIONS: A list of file extensions for those font files
CHARSETFNS: A list of of filetype and charset functions for this device, as described above
Currently the relevant lists are obtained from the global value of variables formed by (PACK* FONTDEVICE PROP), e.g. DISPLAYCHARCOERCIONS for arguments DISPLAY and CHARCOERCIONS. FONTDEVICE can be an atomic device name or a font or fontspec from which the device is extracted.
A priority-ordered list of candidate coercions for a given font or character-set specification is produced by the function COERCEFONTSPEC.
(COERCEFONTSPEC FONTSPEC COERCIONS ) [Function]
COERCIONS is a match/target coercion list, defaulting to the value of the FONTCOERCION property of FONTSPEC's device.
Each element of COERCIONS is a list of (match target) pairs. A match is a list of up to 4 elements to be compared against the corresponding FONTSPEC elements, with * and NIL both treated as match-anything wildcards. If one of the match components is itself a list, the variable * is bound to the corresponding input component and the list is evaluated. Thus the component (<= 2 * 5) will match any sizes between 2 and 5 inclusive.
A target is a similar list that determines the result created from a successful match. A target component * or NIL is interpreted as the corresponding input value. Thus an entry of ((GACHA 10) (TERMINAL 12)) indicates that TERMINAL 12 as a possible coercion for GACHA 10, for any face or rotation. An atomic target is treated as singleton lists, so (GACHA TERMINAL) will coerce any GACHA font into the TERMINAL font of the same size, face, and rotation. List target components are evaluated with * again bound to the corresponding input component. For example, the component (ADD1 *) will produce a font size one greater than the size in FONTSPEC.
(\COERCECHARSET FONTSPEC CHARSET CODE COERCIONS) [Function]
Traverses COERCIONS to find a font with a non-slug charsetinfo for CHARSET. If a character code CODE is provided, the search continues looking for a charset that has non-slug information more specifically about CODE. Returns the search result as a pair (font charsetinfo) that satisfies the search, NIL if no coercion is found. If COERCIONS is a non-NIL atom, that property for the font-device is used. If NIL, then CHARCOERCIONS is used if CODE, otherwise FONTCOERCIONS.
Miscellaneous
The new public function MOVEFONTCHARS moves character information from one code positionto another, in the same or different font.
(MOVEFONTCHARS PAIRS DEVICE DESTFONT DEFAULTSOURCEFONT) [Function]
PAIRS is a list of (source destination) pairs, where each source is either a character indicator (a character name or code), or a pair consisting of a character indicator and a font specification. If a source character name/code is not associated with a font, then DEFAULTSOURCEFONT will be used, otherwise DESTFONT. Each destination is a character name or code. The glyph information for each source will be moved from its font to the destination position in DESTFONT. This moves all the source character parameters to the destination, including the character bitmap for display fonts. This function can be used to fill in glyphs arbitrarily from other fonts/sizes/faces as a backup to the more general glyph-coercion specifications.
If the source of a pair is NIL or the source character is recognized as a slug, a destination-appropriate slug will be inserted at the destination position.
(FLUSHFONTSINCORE FAMILY SIZE FACE ROTATION DEVICE) [Function]
Removes information about the indicated font from the internal caches. A wildcard * can be provided as any of the arguments. FAMILY can be a FONTSPEC etc.
(FONTPROP FONT PROP) [Modified function]
FONTPROP has been extended so that it returns for the property CHARENCODING the font's FONTCHARENCODING. and for the property CHARSETS a list of the numbers of the currently instantiated non-slug charsets. Other charsets may be available, just not yet requested and loaded into memory.
(FONTSPECFROMFILENAME FONTFILE DEVICE ) [Function]
This function replaces the internal \FONTINFOFROMFILENAME. It returns a FONTSPEC based on FONTFILE, the name of a file. The FSDEVICE field of the value will be inferred from DEVICE, if provided. Otherwise the device will be computed by comparing FONTFILE's extension to the items in the fontfile-extension lists corresponding to the entries in IMAGESTREAMTYPES.
(FONTFACETOATOM FACE) [Function]
Returns the atom (e.g. MIR) corresponding to a font face (e.g. (MEDIUM ITALIC REGULAR). Validates FACE if it is already an atom. Causes an error if FACE cannot be interpreted.
More consistent macros have been added for retrieving and installing a charsetinfo for a particular character set in a particular font.
(\GETCHARSETINFO FONTDESC CHARSET) [Macro]
Returns the charset information for CHARSET in FONTDESC, NIL if that charset doesn't exist. (The previous \GETCHARSETINFO created a charsetinfo if one did not already exist--that functionally is provided by the new \INSURECHARSETINFO macro below; also the arguments are swapped)
(\SETCHARSETINFO FONTDESC CHARSET CSINFO) [Modified macro]
Installs CSINFO as the charsetinfo for CHARSET in FONTDESC. (Previous \SETCHARSETFINO took the FONTCHARSETVECTOR as its argument, not the font descriptor.)
(\INSURECHARSETINFO FONTDESC CHARSET) [Macro]
Returns the existing charsetinfo for CHARSET in FONTDESC if it exists. Otherwise installs and returns a new charsetinfo as produced by calling \CREATECHARSET. This is the functionality provided by the previous \GETCHARSETINFO.
The function/macro \GETFONTDESC was a confusing synonym for \COERCEFONTDESC, and \COERCEFONTDESC (not to be confused with COERCEFONTSPEC) had some unbounded recursive branches through FONTCREATE. Both \GETFONTDESC and \COERCEFONTDESC have been removed. The argument-checking aspect of \COERCEFONTDESC is now a subfunction of the general font-argument validator \FONT.CHECKARGS, and FONTCREATE has been substituted for all other occurrences of \COERCEFONTDESC.
There is a new file internal/FONT-DEBUG with a random set of tools that have been helpful in debugging and testing these changes.
(MONOSPACEFONTP FONT CODES SKIPSLUGS RETURNVARIABLES) [Function]
Returns T if all of the characters in FONT that are specified in CODE have the same width. If CODES designates a character set (NIL = character set 0), then all of the characters in that character set are checked. Otherwise, CODES can be a list (startchar endchar) giving a range of characters to be checked. For example, if CODES is (0 127) only the 7-bit Ascii codes of FONT will be examined. Slugs are ignored if SKIPSLUGS, the codes with widths different than the width of the first character are returned if RETURNVARIABLES.
[Other changes to be documented as appropriate]
(SEQUENCE NIL NIL (0 0 0 0) ((PAGE NIL (PAPERSIZE Letter FOLIOINFO (ARABIC "" "") STARTINGPAGE# 1) (0 0 612 792) ((FOLIO NIL (PARALOOKS (QUAD CENTERED) CHARLOOKS (SUPERSCRIPT 0 INVISIBLE OFF SELECTPOINT OFF PROTECTED OFF SIZE 10 FAMILY MODERN OVERLINE OFF STRIKEOUT OFF UNDERLINE OFF EXPANSION REGULAR SLOPE REGULAR WEIGHT MEDIUM INVERTED OFF USERINFO NIL STYLE NIL) FORMATINFO (ARABIC "" "")) (174 36 288 36) NIL) (HEADING NIL (HEADINGTYPE RUNNINGHEAD) (84 744 528 36) NIL) (TEXT NIL NIL (84 96 456 600) NIL))) (ALTERNATE NIL NIL (0 0 0 0) ((PAGE NIL (PAPERSIZE Letter FOLIOINFO (ARABIC "" "")) (0 0 612 792) ((FOLIO NIL (PARALOOKS (QUAD CENTERED) CHARLOOKS (SUPERSCRIPT 0 INVISIBLE OFF SELECTPOINT OFF PROTECTED OFF SIZE 10 FAMILY MODERN OVERLINE OFF STRIKEOUT OFF UNDERLINE OFF EXPANSION REGULAR SLOPE REGULAR WEIGHT MEDIUM INVERTED OFF USERINFO NIL STYLE NIL) FORMATINFO (ARABIC "" "")) (174 36 288 36) NIL) (HEADING NIL (HEADINGTYPE RUNNINGHEAD) (84 744 528 36) NIL) (TEXT NIL NIL (84 96 456 600) NIL))) (PAGE NIL (PAPERSIZE Letter FOLIOINFO (ARABIC "" "")) (0 0 612 792) ((FOLIO NIL (PARALOOKS (QUAD CENTERED) CHARLOOKS (SUPERSCRIPT 0 INVISIBLE OFF SELECTPOINT OFF PROTECTED OFF SIZE 10 FAMILY MODERN OVERLINE OFF STRIKEOUT OFF UNDERLINE OFF EXPANSION REGULAR SLOPE REGULAR WEIGHT MEDIUM INVERTED OFF USERINFO NIL STYLE NIL) FORMATINFO (ARABIC "" "")) (174 36 288 36) NIL) (HEADING NIL (HEADINGTYPE RUNNINGHEAD) (84 744 528 36) NIL) (TEXT NIL NIL (84 96 456 600) NIL)))))))
1$4Ô$Ô4Ô$Ô4Ô $Ô10Ô$10Ô$4Ô$Ô4Ô$Ô4Ô$Ô4ŠŠ8$Ô4ŠŠ8$Ô1ŠŠ8$4Ô$Ô
/MODERN
(CHARPROPS (COLOR . BLACK))0CLASSIC
(CHARPROPS (COLOR . BLACK))/MODERN
(CHARPROPS (COLOR . BLACK))/MODERN
(CHARPROPS (COLOR . BLACK))/MODERN
(CHARPROPS (COLOR . BLACK))/MODERN
(CHARPROPS (COLOR . BLACK))2 HELVETICA
(CHARPROPS (COLOR . BLACK))/MODERN (CHARPROPS (COLOR . BLACK))/MODERN(CHARPROPS (COLOR . BLACK))3
TIMESROMAN$(CHARPROPS (COLOR . BLACK))

 
 HRULE.GETFN  HRULE.GETFN
 HRULE.GETFN 
 HRULE.GETFN
 HRULE.GETFN - vèœ]ìg8İc+(
4
0Y7 Š#9V#f;T:Y 
!\G>

¡
Â'
 Å3Š
 ?6GFóª Q 
\N5:bQ6W<00> /M 

 
E
âŸ
;;=Ã 
H|E³ 
# 7-  1<Š/(¢VÚ/
GCŽH˜
-~ .
(š¹a


)d]O@]WF
X

 Z
 tƒ"

 0ov f
ƒ'

ž 
} 

[MCl
c/ˆ
$à'c
%­Î(
&`*) X0(((TEDIT.LAST.FIND.STRING . "FLUSH") (CLEARGET) (CHARENCODING . MCCS)))PROPS:QDATE:jñÝÉj 3zº